mirror of
https://github.com/vgough/encfs.git
synced 2024-11-21 23:43:26 +01:00
Clean & harden normal tests (#583)
This commit is contained in:
parent
b60939c0ef
commit
f2c4a16ee3
@ -63,17 +63,35 @@ sub sizeVerify
|
|||||||
return $ok;
|
return $ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Wait for a file to appear
|
# Helper to check a file's content
|
||||||
|
sub checkContents
|
||||||
|
{
|
||||||
|
my ($file, $expected, $testName) = @_;
|
||||||
|
|
||||||
|
open(IN, "< $file");
|
||||||
|
my $line = <IN>;
|
||||||
|
is($line, $expected, $testName);
|
||||||
|
|
||||||
|
close IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for a file to (dis)appear
|
||||||
use Time::HiRes qw(usleep);
|
use Time::HiRes qw(usleep);
|
||||||
sub waitForFile
|
sub waitForFile
|
||||||
{
|
{
|
||||||
my $file = shift;
|
my $file = shift;
|
||||||
my $timeout;
|
my $timeout;
|
||||||
$timeout = shift or $timeout = 5;
|
$timeout = shift or $timeout = 5;
|
||||||
for(my $i = $timeout*10; $i > 0; $i--)
|
my $gone;
|
||||||
|
$gone = shift or $gone = 0;
|
||||||
|
for(my $i = $timeout*2; $i > 0; $i--)
|
||||||
{
|
{
|
||||||
-f $file and return 1;
|
if (-f $file) {
|
||||||
usleep(100000); # 0.1 seconds
|
($gone == 0) and return 1;
|
||||||
|
} elsif ($gone == 1) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
usleep(500000); # 0.5 seconds
|
||||||
}
|
}
|
||||||
print "# timeout waiting for '$file' to appear\n";
|
print "# timeout waiting for '$file' to appear\n";
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/perl -w
|
#!/usr/bin/perl -w
|
||||||
|
|
||||||
# Test EncFS normal and paranoid mode
|
# Test EncFS standard and paranoid mode
|
||||||
|
|
||||||
use Test::More tests => 136;
|
use Test::More tests => 144;
|
||||||
use File::Path;
|
use File::Path;
|
||||||
use File::Copy;
|
use File::Copy;
|
||||||
use File::Temp;
|
use File::Temp;
|
||||||
@ -11,24 +11,22 @@ use IO::Handle;
|
|||||||
require("integration/common.pl");
|
require("integration/common.pl");
|
||||||
|
|
||||||
my $tempDir = $ENV{'TMPDIR'} || "/tmp";
|
my $tempDir = $ENV{'TMPDIR'} || "/tmp";
|
||||||
|
|
||||||
if($^O eq "linux" and $tempDir eq "/tmp") {
|
if($^O eq "linux" and $tempDir eq "/tmp") {
|
||||||
# On Linux, /tmp is often a tmpfs mount that does not support
|
# On Linux, /tmp is often a tmpfs mount that does not
|
||||||
# extended attributes. Use /var/tmp instead.
|
# support extended attributes. Use /var/tmp instead.
|
||||||
$tempDir = "/var/tmp";
|
$tempDir = "/var/tmp";
|
||||||
}
|
}
|
||||||
|
|
||||||
# Find attr binary
|
# Find attr binary, Linux
|
||||||
# Linux
|
|
||||||
my $setattr = "attr -s encfs -V hello";
|
my $setattr = "attr -s encfs -V hello";
|
||||||
my $getattr = "attr -g encfs";
|
my $getattr = "attr -g encfs";
|
||||||
if(system("which xattr > /dev/null 2>&1") == 0)
|
if(system("which xattr >/dev/null 2>&1") == 0)
|
||||||
{
|
{
|
||||||
# Mac OS X
|
# Mac OS X
|
||||||
$setattr = "xattr -sw encfs hello";
|
$setattr = "xattr -sw encfs hello";
|
||||||
$getattr = "xattr -sp encfs";
|
$getattr = "xattr -sp encfs";
|
||||||
}
|
}
|
||||||
if(system("which lsextattr > /dev/null 2>&1") == 0)
|
if(system("which lsextattr >/dev/null 2>&1") == 0)
|
||||||
{
|
{
|
||||||
# FreeBSD
|
# FreeBSD
|
||||||
$setattr = "setextattr -h user encfs hello";
|
$setattr = "setextattr -h user encfs hello";
|
||||||
@ -53,188 +51,133 @@ elsif (defined($ENV{'SUDO_TESTS'}))
|
|||||||
$sudo_cmd="sudo";
|
$sudo_cmd="sudo";
|
||||||
}
|
}
|
||||||
|
|
||||||
# test filesystem in standard config mode
|
# Test filesystem in standard config mode
|
||||||
&runTests('standard');
|
my $mode="standard";
|
||||||
|
&runTests();
|
||||||
|
|
||||||
# test in paranoia mode
|
# Test filesystem in paranoia config mode
|
||||||
&runTests('paranoia');
|
$mode="paranoia";
|
||||||
|
&runTests();
|
||||||
|
|
||||||
# Wrapper function - runs all tests in the specified mode
|
# Run all tests in the specified mode
|
||||||
sub runTests
|
sub runTests
|
||||||
{
|
{
|
||||||
my $mode = shift;
|
print STDERR "\nrunTests: mode=$mode xattr=$have_xattr sudo=";
|
||||||
print STDERR "\nrunTests: mode=$mode sudo=";
|
print STDERR (defined($sudo_cmd) ? "1" : "0")."\n";
|
||||||
print STDERR (defined($sudo_cmd) ? "on" : "off")."\n";
|
|
||||||
|
|
||||||
&newWorkingDir;
|
&newWorkingDir;
|
||||||
|
&mount;
|
||||||
|
&remount;
|
||||||
|
&configFromPipe;
|
||||||
|
|
||||||
my $hardlinks = 1;
|
|
||||||
if($mode eq 'standard')
|
|
||||||
{
|
|
||||||
&mount("--standard");
|
|
||||||
} elsif($mode eq 'paranoia')
|
|
||||||
{
|
|
||||||
&mount("--paranoia");
|
|
||||||
$hardlinks = 0; # no hardlinks in paranoia mode
|
|
||||||
&corruption;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
die "invalid test mode";
|
|
||||||
}
|
|
||||||
|
|
||||||
# tests..
|
|
||||||
&fileCreation;
|
&fileCreation;
|
||||||
&links($hardlinks);
|
|
||||||
&truncate;
|
|
||||||
&renames;
|
&renames;
|
||||||
&internalModification;
|
&links;
|
||||||
&grow;
|
&grow;
|
||||||
|
&truncate;
|
||||||
|
&internalModification;
|
||||||
&umask0777;
|
&umask0777;
|
||||||
&create_unmount_remount;
|
|
||||||
|
&corruption;
|
||||||
&checkReadError;
|
&checkReadError;
|
||||||
&checkWriteError;
|
&checkWriteError;
|
||||||
|
|
||||||
&configFromPipe;
|
|
||||||
&cleanup;
|
&cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helper function
|
# Helper to convert plain-text filename to encrypted filename
|
||||||
|
sub encName
|
||||||
|
{
|
||||||
|
my $plain = shift;
|
||||||
|
my $enc = qx(./build/encfsctl encode --extpass="echo test" $ciphertext $plain);
|
||||||
|
chomp($enc);
|
||||||
|
return $enc;
|
||||||
|
}
|
||||||
|
|
||||||
# Create a new empty working directory
|
# Create a new empty working directory
|
||||||
sub newWorkingDir
|
sub newWorkingDir
|
||||||
{
|
{
|
||||||
our $workingDir = mkdtemp("$tempDir/encfs-tests-XXXX")
|
our $workingDir = mkdtemp("$tempDir/encfs-normal-tests-XXXX") || BAIL_OUT("Could not create temporary directory");
|
||||||
|| BAIL_OUT("Could not create temporary directory");
|
|
||||||
|
|
||||||
our $raw = "$workingDir/raw";
|
our $ciphertext = "$workingDir/ciphertext";
|
||||||
our $crypt = "$workingDir/crypt";
|
mkdir($ciphertext) || BAIL_OUT("Could not create $ciphertext: $!");
|
||||||
|
|
||||||
|
our $decrypted = "$workingDir/decrypted";
|
||||||
if ($^O eq "cygwin")
|
if ($^O eq "cygwin")
|
||||||
{
|
{
|
||||||
$crypt = "/cygdrive/x";
|
$decrypted = "/cygdrive/x";
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
|
||||||
# Test Corruption
|
|
||||||
# Modify the encrypted file and verify that the MAC check detects it
|
|
||||||
sub corruption
|
|
||||||
{
|
|
||||||
ok( open(OUT, "+> $crypt/corrupt") && print(OUT "12345678901234567890")
|
|
||||||
&& close(OUT), "create corruption-test file" );
|
|
||||||
|
|
||||||
|
|
||||||
$e = encName("corrupt");
|
|
||||||
ok( open(OUT, ">> $raw/$e") && print(OUT "garbage") && close(OUT),
|
|
||||||
"corrupting raw file");
|
|
||||||
|
|
||||||
ok( open(IN, "< $crypt/corrupt"), "open corrupted file");
|
|
||||||
my $content;
|
|
||||||
$result = read(IN, $content, 20);
|
|
||||||
# Cygwin returns EINVAL for now
|
|
||||||
ok(($!{EBADMSG} || $!{EINVAL}) && (! defined $result), "corrupted file with MAC returns read error: $!");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test internal modification
|
|
||||||
# Create a file of fixed size and overwrite data at different offsets
|
|
||||||
# (like a database would do)
|
|
||||||
sub internalModification
|
|
||||||
{
|
|
||||||
$ofile = "$workingDir/crypt-internal-$$";
|
|
||||||
writeZeroes($ofile, 2*1024);
|
|
||||||
ok(copy($ofile, "$crypt/internal"), "copying crypt-internal file");
|
|
||||||
|
|
||||||
open(my $out1, "+<", "$crypt/internal");
|
|
||||||
open(my $out2, "+<", $ofile);
|
|
||||||
|
|
||||||
@fhs = ($out1, $out2);
|
|
||||||
|
|
||||||
$ori = md5fh($out1);
|
|
||||||
$b = md5fh($out2);
|
|
||||||
|
|
||||||
ok( $ori eq $b, "random file md5 matches");
|
|
||||||
|
|
||||||
my @offsets = (10, 30, 1020, 1200);
|
|
||||||
foreach my $o (@offsets)
|
|
||||||
{
|
{
|
||||||
foreach my $fh(@fhs) {
|
mkdir($decrypted) || BAIL_OUT("Could not create $decrypted: $!");
|
||||||
seek($fh, $o, 0);
|
|
||||||
print($fh "garbagegarbagegarbagegarbagegarbage");
|
|
||||||
}
|
|
||||||
$a=md5fh($out1);
|
|
||||||
$b=md5fh($out2);
|
|
||||||
ok( ($a eq $b) && ($a ne $ori), "internal modification at $o");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close($out1);
|
|
||||||
close($out2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test renames
|
# Unmount and delete mountpoint
|
||||||
sub renames
|
sub cleanup
|
||||||
{
|
{
|
||||||
ok( open(F, ">$crypt/orig-name") && close F, "create file for rename test");
|
portable_unmount($decrypted);
|
||||||
ok( -f "$crypt/orig-name", "file exists");
|
ok(waitForFile("$decrypted/mount", 5, 1), "mount test file gone") || BAIL_OUT("");
|
||||||
|
|
||||||
ok( rename("$crypt/orig-name", "$crypt/2nd-name"), "rename");
|
rmdir $decrypted;
|
||||||
ok( ! -f "$crypt/orig-name", "file exists");
|
ok(! -d $decrypted, "unmount ok, mount point removed");
|
||||||
ok( -f "$crypt/2nd-name", "file exists");
|
|
||||||
|
|
||||||
# rename directory with contents
|
rmtree($workingDir);
|
||||||
ok( mkpath("$crypt/orig-dir/foo"), "mkdir for rename test");
|
ok(! -d $workingDir, "working dir removed");
|
||||||
ok( open(F, ">$crypt/orig-dir/foo/bar") && close F, "make file");
|
|
||||||
|
|
||||||
ok( rename("$crypt/orig-dir", "$crypt/new-dir"), "rename dir");
|
|
||||||
ok( -f "$crypt/new-dir/foo/bar", "dir rename contents");
|
|
||||||
|
|
||||||
# TODO: rename failure? (check undo works)
|
|
||||||
|
|
||||||
# check time stamps of files on rename
|
|
||||||
my $mtime = (stat "$crypt/2nd-name")[9];
|
|
||||||
# change time to 60 seconds earlier
|
|
||||||
my $olderTime = $mtime - 60;
|
|
||||||
ok( utime($olderTime, $olderTime, "$crypt/2nd-name"), "change time");
|
|
||||||
|
|
||||||
ok( rename("$crypt/2nd-name", "$crypt/3rd-name"), "rename");
|
|
||||||
is( (stat "$crypt/3rd-name")[9], $olderTime, "time unchanged by rename");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test truncate and grow
|
# Mount the filesystem
|
||||||
sub truncate
|
sub mount
|
||||||
{
|
{
|
||||||
# write to file, then truncate it
|
delete $ENV{"ENCFS6_CONFIG"};
|
||||||
ok( open(OUT, "+> $crypt/trunc"), "create truncate-test file");
|
|
||||||
autoflush OUT 1;
|
|
||||||
print OUT "12345678901234567890";
|
|
||||||
|
|
||||||
is( -s "$crypt/trunc", 20, "initial file size" );
|
system("./build/encfs --extpass=\"echo test\" --$mode $ciphertext $decrypted");
|
||||||
|
ok($? == 0, "encfs mount command returns 0") || BAIL_OUT("");
|
||||||
ok( truncate(OUT, 10), "truncate" );
|
ok(-f "$ciphertext/.encfs6.xml", "created control file") || BAIL_OUT("");
|
||||||
|
|
||||||
is( -s "$crypt/trunc", 10, "truncated file size");
|
|
||||||
is( qx(cat "$crypt/trunc"), "1234567890", "truncated file contents");
|
|
||||||
|
|
||||||
# try growing the file as well.
|
|
||||||
ok( truncate(OUT, 30), "truncate extend");
|
|
||||||
is( -s "$crypt/trunc", 30, "truncated file size");
|
|
||||||
|
|
||||||
seek(OUT, 30, 0);
|
|
||||||
print OUT "12345";
|
|
||||||
is( -s "$crypt/trunc", 35, "truncated file size");
|
|
||||||
|
|
||||||
is( md5fh(*OUT), "5f170cc34b1944d75d86cc01496292df",
|
|
||||||
"content digest");
|
|
||||||
|
|
||||||
# try crossing block boundaries
|
|
||||||
seek(OUT, 10000,0);
|
|
||||||
print OUT "abcde";
|
|
||||||
|
|
||||||
is( md5fh(*OUT), "117a51c980b64dcd21df097d02206f98",
|
|
||||||
"content digest");
|
|
||||||
|
|
||||||
# then truncate back to 35 chars
|
|
||||||
truncate(OUT, 35);
|
|
||||||
is( md5fh(*OUT), "5f170cc34b1944d75d86cc01496292df",
|
|
||||||
"content digest");
|
|
||||||
|
|
||||||
|
open(OUT, "> $ciphertext/" . encName("mount"));
|
||||||
close OUT;
|
close OUT;
|
||||||
|
ok(waitForFile("$decrypted/mount"), "mount test file exists") || BAIL_OUT("");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remount and verify content, testing -c option at the same time
|
||||||
|
sub remount
|
||||||
|
{
|
||||||
|
my $contents = "hello world";
|
||||||
|
open(OUT, "> $decrypted/remount");
|
||||||
|
print OUT $contents;
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
portable_unmount($decrypted);
|
||||||
|
ok(waitForFile("$decrypted/mount", 5, 1), "mount test file gone") || BAIL_OUT("");
|
||||||
|
|
||||||
|
rename("$ciphertext/.encfs6.xml", "$ciphertext/.encfs6_moved.xml");
|
||||||
|
system("./build/encfs -c $ciphertext/.encfs6_moved.xml --extpass=\"echo test\" $ciphertext $decrypted");
|
||||||
|
ok($? == 0, "encfs remount command returns 0") || BAIL_OUT("");
|
||||||
|
ok(waitForFile("$decrypted/mount"), "mount test file exists") || BAIL_OUT("");
|
||||||
|
rename("$ciphertext/.encfs6_moved.xml", "$ciphertext/.encfs6.xml");
|
||||||
|
|
||||||
|
checkContents("$decrypted/remount", $contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
# Read the configuration from a named pipe (https://github.com/vgough/encfs/issues/253)
|
||||||
|
sub configFromPipe
|
||||||
|
{
|
||||||
|
portable_unmount($decrypted);
|
||||||
|
ok(waitForFile("$decrypted/mount", 5, 1), "mount test file gone") || BAIL_OUT("");
|
||||||
|
|
||||||
|
rename("$ciphertext/.encfs6.xml", "$ciphertext/.encfs6_moved.xml");
|
||||||
|
system("mkfifo $ciphertext/.encfs6.xml");
|
||||||
|
my $child = fork();
|
||||||
|
unless ($child) {
|
||||||
|
system("./build/encfs --extpass=\"echo test\" $ciphertext $decrypted");
|
||||||
|
exit($? >> 8);
|
||||||
|
}
|
||||||
|
system("cat $ciphertext/.encfs6_moved.xml > $ciphertext/.encfs6.xml");
|
||||||
|
waitpid($child, 0);
|
||||||
|
ok($? == 0, "encfs piped command returns 0") || BAIL_OUT("");
|
||||||
|
ok(waitForFile("$decrypted/mount"), "mount test file exists") || BAIL_OUT("");
|
||||||
|
rename("$ciphertext/.encfs6_moved.xml", "$ciphertext/.encfs6.xml");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test file creation and removal
|
# Test file creation and removal
|
||||||
@ -242,31 +185,102 @@ sub fileCreation
|
|||||||
{
|
{
|
||||||
# first be sure .encfs6.xml does not show up
|
# first be sure .encfs6.xml does not show up
|
||||||
my $f = encName(".encfs6.xml");
|
my $f = encName(".encfs6.xml");
|
||||||
cmp_ok( length($f), '>', 8, "encrypted name ok" );
|
cmp_ok(length($f), '>', 8, "encrypted name ok");
|
||||||
ok( ! -f "$raw/$f", "configuration file .encfs6.xml not visible in $raw" );
|
ok(! -f "$ciphertext/$f", "configuration file .encfs6.xml not visible in $ciphertext");
|
||||||
|
|
||||||
# create a file
|
# create a file
|
||||||
qx(date > "$crypt/df.txt");
|
system("cat $0 > $decrypted/create");
|
||||||
ok( -f "$crypt/df.txt", "file created" ) || BAIL_OUT("file create failed");
|
ok(-f "$decrypted/create", "file created" ) || BAIL_OUT("file create failed");
|
||||||
|
|
||||||
# ensure there is an encrypted version.
|
# ensure there is an encrypted version.
|
||||||
my $c = encName("df.txt");
|
my $c = encName("create");
|
||||||
cmp_ok( length($c), '>', 8, "encrypted name ok" );
|
cmp_ok(length($c), '>', 8, "encrypted name ok");
|
||||||
ok( -f "$raw/$c", "encrypted file $raw/$c created" );
|
ok(-f "$ciphertext/$c", "encrypted file $ciphertext/$c created");
|
||||||
|
|
||||||
# check contents
|
# check contents
|
||||||
my $count = qx(grep -c crypt-$$ "$crypt/df.txt");
|
system("diff $0 $decrypted/create");
|
||||||
isnt(scalar($count), 0, "encrypted file readable");
|
ok($? == 0, "encrypted file readable");
|
||||||
|
|
||||||
unlink "$crypt/df.txt";
|
unlink "$decrypted/create";
|
||||||
ok( ! -f "$crypt/df.txt", "file removal" );
|
ok(! -f "$decrypted/create", "file removal");
|
||||||
ok( ! -f "$raw/$c", "file removal" );
|
ok(! -f "$ciphertext/$c", "file removal");
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test renames
|
||||||
|
sub renames
|
||||||
|
{
|
||||||
|
ok(open(F, ">$decrypted/rename-orig") && close F, "create file for rename test");
|
||||||
|
ok(-f "$decrypted/rename-orig", "file exists");
|
||||||
|
|
||||||
|
ok(rename("$decrypted/rename-orig", "$decrypted/rename-new"), "rename");
|
||||||
|
ok(! -f "$decrypted/rename-orig", "file exists");
|
||||||
|
ok(-f "$decrypted/rename-new", "file exists");
|
||||||
|
|
||||||
|
# rename directory with contents
|
||||||
|
ok(mkpath("$decrypted/rename-dir-orig/foo"), "mkdir for rename test");
|
||||||
|
ok(open(F, ">$decrypted/rename-dir-orig/foo/bar") && close F, "make file");
|
||||||
|
|
||||||
|
ok(rename("$decrypted/rename-dir-orig", "$decrypted/rename-dir-new"), "rename dir");
|
||||||
|
ok(-f "$decrypted/rename-dir-new/foo/bar", "dir rename contents");
|
||||||
|
|
||||||
|
# TODO: rename failure? (check undo works)
|
||||||
|
|
||||||
|
# check time stamps of files on rename
|
||||||
|
my $mtime = (stat "$decrypted/rename-new")[9];
|
||||||
|
# change time to 60 seconds earlier
|
||||||
|
my $olderTime = $mtime - 60;
|
||||||
|
ok(utime($olderTime, $olderTime, "$decrypted/rename-new"), "change time");
|
||||||
|
|
||||||
|
ok(rename("$decrypted/rename-new", "$decrypted/rename-time"), "rename");
|
||||||
|
is((stat "$decrypted/rename-time")[9], $olderTime, "time unchanged by rename");
|
||||||
|
|
||||||
|
# TODO: # check time stamps of directories on rename (https://github.com/vgough/encfs/pull/541)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test symlinks & hardlinks, and extended attributes
|
||||||
|
sub links
|
||||||
|
{
|
||||||
|
my $contents = "hello world";
|
||||||
|
ok(open(OUT, "> $decrypted/link-data"), "create file for link test");
|
||||||
|
print OUT $contents;
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
# symlinks
|
||||||
|
ok(symlink("$decrypted/link-data", "$decrypted/link-data-fqn") , "fqn symlink");
|
||||||
|
checkContents("$decrypted/link-data-fqn", $contents, "fqn link traversal");
|
||||||
|
is(readlink("$decrypted/link-data-fqn"), "$decrypted/link-data", "read fqn symlink");
|
||||||
|
|
||||||
|
ok(symlink("link-data", "$decrypted/link-data-rel"), "local symlink");
|
||||||
|
checkContents("$decrypted/link-data-rel", $contents, "rel link traversal");
|
||||||
|
is(readlink("$decrypted/link-data-rel"), "link-data", "read rel symlink");
|
||||||
|
|
||||||
|
if ($mode eq "standard")
|
||||||
|
{
|
||||||
|
ok(link("$decrypted/link-data", "$decrypted/link-data-hard"), "hard link");
|
||||||
|
checkContents("$decrypted/link-data-hard", $contents, "hardlink read");
|
||||||
|
}
|
||||||
|
|
||||||
|
# extended attributes
|
||||||
|
SKIP: {
|
||||||
|
skip "No xattr support", 3 unless ($have_xattr);
|
||||||
|
|
||||||
|
system("$setattr $decrypted/link-data");
|
||||||
|
my $rc = $?;
|
||||||
|
is($rc, 0, "extended attributes can be set (return code was $rc)");
|
||||||
|
system("$getattr $decrypted/link-data");
|
||||||
|
$rc = $?;
|
||||||
|
is($rc, 0, "extended attributes can be get (return code was $rc)");
|
||||||
|
# this is suppused to fail, so get rid of the error message
|
||||||
|
system("$getattr $decrypted/link-data-rel 2>/dev/null");
|
||||||
|
$rc = $?;
|
||||||
|
isnt($rc, 0, "extended attributes operations do not follow symlinks (return code was $rc)");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test file growth
|
# Test file growth
|
||||||
sub grow
|
sub grow
|
||||||
{
|
{
|
||||||
open(my $fh_a, "+>$crypt/grow");
|
open(my $fh_a, "+>$decrypted/grow");
|
||||||
open(my $fh_b, "+>$workingDir/grow");
|
open(my $fh_b, "+>$workingDir/grow");
|
||||||
|
|
||||||
my $d = "1234567"; # Length 7 so we are not aligned to the block size
|
my $d = "1234567"; # Length 7 so we are not aligned to the block size
|
||||||
@ -276,195 +290,130 @@ sub grow
|
|||||||
my $errs = 0;
|
my $errs = 0;
|
||||||
|
|
||||||
my $i;
|
my $i;
|
||||||
for($i=1; $i<1000; $i++)
|
for ($i=1; $i<1000; $i++)
|
||||||
{
|
{
|
||||||
print($fh_a $d);
|
print($fh_a $d);
|
||||||
print($fh_b $d);
|
print($fh_b $d);
|
||||||
|
|
||||||
my $a = md5fh($fh_a);
|
my $a = md5fh($fh_a);
|
||||||
my $b = md5fh($fh_b);
|
my $b = md5fh($fh_b);
|
||||||
|
|
||||||
my $size = $len * $i;
|
my $size = $len * $i;
|
||||||
|
|
||||||
# md5sums must be identical but must have changed
|
# md5sums must be identical but must have changed
|
||||||
if($a ne $b || $a eq $old)
|
if($a ne $b || $a eq $old)
|
||||||
{
|
{
|
||||||
$errs++;
|
$errs++;
|
||||||
}
|
}
|
||||||
|
|
||||||
$old = $a;
|
$old = $a;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok($errs == 0, "grow file by $len bytes, $i times");
|
ok($errs == 0, "grow file by $len bytes, $i times");
|
||||||
|
|
||||||
close($fh_a);
|
close($fh_a);
|
||||||
close($fh_b);
|
close($fh_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helper function
|
# Test truncate and grow
|
||||||
# Check a file's content
|
sub truncate
|
||||||
sub checkContents
|
|
||||||
{
|
{
|
||||||
my ($file, $expected, $testName) = @_;
|
# write to file, then truncate it
|
||||||
|
ok(open(OUT, "+> $decrypted/truncate"), "create truncate-test file");
|
||||||
|
autoflush OUT 1;
|
||||||
|
print OUT "1234567890ABCDEFGHIJ";
|
||||||
|
|
||||||
open(IN, "< $file");
|
is(-s "$decrypted/truncate", 20, "initial file size");
|
||||||
my $line = <IN>;
|
|
||||||
is( $line, $expected, $testName );
|
|
||||||
|
|
||||||
close IN;
|
ok(truncate(OUT, 10), "truncate");
|
||||||
}
|
|
||||||
|
|
||||||
# Helper function
|
is(-s "$decrypted/truncate", 10, "truncated file size");
|
||||||
# Convert plain-text filename to encrypted filename
|
is(qx(cat "$decrypted/truncate"), "1234567890", "truncated file contents");
|
||||||
sub encName
|
|
||||||
{
|
|
||||||
my $plain = shift;
|
|
||||||
my $enc = qx(./build/encfsctl encode --extpass="echo test" $raw $plain);
|
|
||||||
chomp($enc);
|
|
||||||
return $enc;
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test symlinks & hardlinks, and extended attributes
|
# try growing the file as well.
|
||||||
sub links
|
ok(truncate(OUT, 30), "truncate extend");
|
||||||
{
|
is(-s "$decrypted/truncate", 30, "truncated file size");
|
||||||
my $hardlinkTests = shift;
|
|
||||||
|
seek(OUT, 30, 0);
|
||||||
|
print OUT "12345";
|
||||||
|
is(-s "$decrypted/truncate", 35, "truncated file size");
|
||||||
|
|
||||||
|
is(md5fh(*OUT), "5f170cc34b1944d75d86cc01496292df", "content digest");
|
||||||
|
|
||||||
|
# try crossing block boundaries
|
||||||
|
seek(OUT, 10000,0);
|
||||||
|
print OUT "abcde";
|
||||||
|
|
||||||
|
is(md5fh(*OUT), "117a51c980b64dcd21df097d02206f98", "content digest");
|
||||||
|
|
||||||
|
# then truncate back to 35 chars
|
||||||
|
truncate(OUT, 35);
|
||||||
|
is(md5fh(*OUT), "5f170cc34b1944d75d86cc01496292df", "content digest");
|
||||||
|
|
||||||
my $contents = "hello world";
|
|
||||||
ok( open(OUT, "> $crypt/data"), "create file for link test" );
|
|
||||||
print OUT $contents;
|
|
||||||
close OUT;
|
close OUT;
|
||||||
|
|
||||||
# symlinks
|
|
||||||
ok( symlink("$crypt/data", "$crypt/data-fqn") , "fqn symlink");
|
|
||||||
checkContents("$crypt/data-fqn", $contents, "fqn link traversal");
|
|
||||||
is( readlink("$crypt/data-fqn"), "$crypt/data", "read fqn symlink");
|
|
||||||
|
|
||||||
ok( symlink("data", "$crypt/data-rel"), "local symlink");
|
|
||||||
checkContents("$crypt/data-rel", $contents, "rel link traversal");
|
|
||||||
is( readlink("$crypt/data-rel"), "data", "read rel symlink");
|
|
||||||
|
|
||||||
SKIP: {
|
|
||||||
skip "No hardlink support", 2 unless $hardlinkTests;
|
|
||||||
|
|
||||||
ok( link("$crypt/data", "$crypt/data.2"), "hard link");
|
|
||||||
checkContents("$crypt/data.2", $contents, "hardlink read");
|
|
||||||
};
|
|
||||||
|
|
||||||
# extended attributes
|
|
||||||
my $return_code = ($have_xattr) ? system("$setattr $crypt/data") : 0;
|
|
||||||
is($return_code, 0, "extended attributes can be set (return code was $return_code)");
|
|
||||||
$return_code = ($have_xattr) ? system("$getattr $crypt/data") : 0;
|
|
||||||
is($return_code, 0, "extended attributes can be get (return code was $return_code)");
|
|
||||||
# this is suppused to fail, so get rid of the error message
|
|
||||||
$return_code = ($have_xattr) ? system("$getattr $crypt/data-rel 2> /dev/null") : 1;
|
|
||||||
isnt($return_code, 0, "extended attributes operations do not follow symlinks (return code was $return_code)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test mount
|
# Test internal modification
|
||||||
# Leaves the filesystem mounted - also used as a helper function
|
# Create a file of fixed size and overwrite data at different offsets
|
||||||
sub mount
|
# (like a database would do)
|
||||||
|
sub internalModification
|
||||||
{
|
{
|
||||||
my $args = shift;
|
$ofile = "$workingDir/internal";
|
||||||
|
writeZeroes($ofile, 2*1024);
|
||||||
|
ok(copy($ofile, "$decrypted/internal"), "copying crypt-internal file");
|
||||||
|
|
||||||
# When these fail, the rest of the tests makes no sense
|
open(my $out1, "+<", "$decrypted/internal");
|
||||||
mkdir($raw) || BAIL_OUT("Could not create $raw: $!");
|
open(my $out2, "+<", $ofile);
|
||||||
if ($^O ne "cygwin")
|
|
||||||
|
@fhs = ($out1, $out2);
|
||||||
|
|
||||||
|
$ori = md5fh($out1);
|
||||||
|
$b = md5fh($out2);
|
||||||
|
|
||||||
|
ok($ori eq $b, "random file md5 matches");
|
||||||
|
|
||||||
|
my @offsets = (10, 30, 1020, 1200);
|
||||||
|
foreach my $o (@offsets)
|
||||||
{
|
{
|
||||||
mkdir($crypt) || BAIL_OUT("Could not create $crypt: $!");
|
foreach my $fh (@fhs)
|
||||||
|
{
|
||||||
|
seek($fh, $o, 0);
|
||||||
|
print($fh "garbagegarbagegarbagegarbagegarbage");
|
||||||
|
}
|
||||||
|
$a = md5fh($out1);
|
||||||
|
$b = md5fh($out2);
|
||||||
|
ok(($a eq $b) && ($a ne $ori), "internal modification at $o");
|
||||||
}
|
}
|
||||||
|
|
||||||
delete $ENV{"ENCFS6_CONFIG"};
|
close($out1);
|
||||||
remount($args);
|
close($out2);
|
||||||
ok( $? == 0, "encfs command returns 0") || BAIL_OUT("");
|
|
||||||
ok( -f "$raw/.encfs6.xml", "created control file") || BAIL_OUT("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helper function
|
# Test that we can create and write to a a 0777 file (https://github.com/vgough/encfs/issues/181)
|
||||||
# Mount without any prior checks
|
|
||||||
sub remount
|
|
||||||
{
|
|
||||||
my $args = shift;
|
|
||||||
my $cmdline = "./build/encfs --extpass=\"echo test\" $args $raw $crypt 2>&1";
|
|
||||||
# This makes sure we get to see stderr ^
|
|
||||||
system($cmdline);
|
|
||||||
}
|
|
||||||
|
|
||||||
# Helper function
|
|
||||||
# Unmount and delete mountpoint
|
|
||||||
sub cleanup
|
|
||||||
{
|
|
||||||
portable_unmount($crypt);
|
|
||||||
|
|
||||||
rmdir $crypt;
|
|
||||||
ok( ! -d $crypt, "unmount ok, mount point removed");
|
|
||||||
|
|
||||||
rmtree($workingDir);
|
|
||||||
ok( ! -d $workingDir, "working dir removed");
|
|
||||||
}
|
|
||||||
|
|
||||||
# Test that we can create and write to a a file even if umask is set to 0777
|
|
||||||
# Regression test for bug https://github.com/vgough/encfs/issues/181
|
|
||||||
sub umask0777
|
sub umask0777
|
||||||
{
|
{
|
||||||
my $old = umask(0777);
|
my $old = umask(0777);
|
||||||
ok(open(my $fh, "+>$crypt/umask0777"), "open with umask 0777");
|
ok(open(my $fh, "+>$decrypted/umask0777"), "open with umask 0777");
|
||||||
close($fh);
|
close($fh);
|
||||||
umask($old);
|
umask($old);
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test that we can read the configuration from a named pipe
|
# Test Corruption
|
||||||
# Regression test for https://github.com/vgough/encfs/issues/253
|
# Modify the encrypted file and verify that the MAC check detects it
|
||||||
sub configFromPipe
|
sub corruption
|
||||||
{
|
{
|
||||||
portable_unmount($crypt);
|
if ($mode ne "paranoia")
|
||||||
rename("$raw/.encfs6.xml", "$raw/.encfs6.xml.orig");
|
|
||||||
system("mkfifo $raw/.encfs6.xml");
|
|
||||||
my $child = fork();
|
|
||||||
unless ($child) {
|
|
||||||
&remount("--standard");
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
system("cat $raw/.encfs6.xml.orig > $raw/.encfs6.xml");
|
|
||||||
waitpid($child, 0);
|
|
||||||
ok( 0 == $?, "encfs mount with named pipe based config failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
sub create_unmount_remount
|
|
||||||
{
|
|
||||||
my $crypt = "$workingDir/create_remount.crypt";
|
|
||||||
my $mnt = "$workingDir/create_remount.mnt";
|
|
||||||
if ($^O eq "cygwin")
|
|
||||||
{
|
{
|
||||||
$mnt = "/cygdrive/y";
|
return;
|
||||||
}
|
|
||||||
mkdir($crypt) || BAIL_OUT($!);
|
|
||||||
if ($^O ne "cygwin")
|
|
||||||
{
|
|
||||||
mkdir($mnt) || BAIL_OUT($!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
ok(open(OUT, "+> $decrypted/corruption") && print(OUT "12345678901234567890")
|
||||||
ok( $? == 0, "encfs command returns 0") || return;
|
&& close(OUT), "create corruption-test file");
|
||||||
ok( -f "$crypt/.encfs6.xml", "created control file") || return;
|
|
||||||
|
|
||||||
# Write some text
|
|
||||||
my $contents = "hello world\n";
|
|
||||||
ok( open(OUT, "> $mnt/test_file_1"), "write content");
|
|
||||||
print OUT $contents;
|
|
||||||
close OUT;
|
|
||||||
|
|
||||||
# Unmount
|
$e = encName("corruption");
|
||||||
portable_unmount($mnt);
|
ok(open(OUT, ">> $ciphertext/$e") && print(OUT "garbage") && close(OUT), "corrupting raw file");
|
||||||
|
|
||||||
# Mount again, testing -c at the same time
|
ok(open(IN, "< $decrypted/corruption"), "open corrupted file");
|
||||||
rename("$crypt/.encfs6.xml", "$crypt/.encfs6_moved.xml");
|
my $content;
|
||||||
system("./build/encfs -c $crypt/.encfs6_moved.xml --extpass=\"echo test\" $crypt $mnt 2>&1");
|
$result = read(IN, $content, 20);
|
||||||
ok( $? == 0, "encfs command returns 0") || return;
|
# Cygwin returns EINVAL for now
|
||||||
|
ok(($!{EBADMSG} || $!{EINVAL}) && (! defined $result), "corrupted file with MAC returns read error: $!");
|
||||||
# Check if content is still there
|
|
||||||
checkContents("$mnt/test_file_1", $contents);
|
|
||||||
|
|
||||||
portable_unmount($mnt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test that read errors are correctly thrown up to us
|
# Test that read errors are correctly thrown up to us
|
||||||
@ -478,33 +427,41 @@ sub checkReadError
|
|||||||
sub checkWriteError
|
sub checkWriteError
|
||||||
{
|
{
|
||||||
# No OSX impl (for now, feel free to find how to), and requires "sudo".
|
# No OSX impl (for now, feel free to find how to), and requires "sudo".
|
||||||
if($^O eq "darwin" || !defined($sudo_cmd)) {
|
SKIP: {
|
||||||
ok(1, "write error");
|
skip "No tmpfs/sudo support", 6 unless ($^O ne "darwin" && defined($sudo_cmd));
|
||||||
ok(1, "write error");
|
|
||||||
ok(1, "write error");
|
rename("$ciphertext/.encfs6.xml", "$workingDir/.encfs6.xml");
|
||||||
ok(1, "write error");
|
$ENV{"ENCFS6_CONFIG"} = "$workingDir/.encfs6.xml";
|
||||||
}
|
|
||||||
else {
|
my $ciphertext = "$ciphertext.tmpfs";
|
||||||
my $crypt = "$workingDir/checkWriteError.crypt";
|
mkdir($ciphertext) || BAIL_OUT("Could not create $ciphertext: $!");
|
||||||
my $mnt = "$workingDir/checkWriteError.mnt";
|
my $decrypted = "$decrypted.tmpfs";
|
||||||
if ($^O eq "cygwin")
|
if ($^O eq "cygwin")
|
||||||
{
|
{
|
||||||
$mnt = "/cygdrive/z";
|
$decrypted = "/cygdrive/y";
|
||||||
}
|
}
|
||||||
mkdir($crypt) || BAIL_OUT($!);
|
else
|
||||||
if ($^O ne "cygwin")
|
{
|
||||||
{
|
mkdir($decrypted) || BAIL_OUT("Could not create $decrypted: $!");
|
||||||
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 $ciphertext");
|
||||||
ok( $? == 0, "mount command returns 0") || return;
|
ok($? == 0, "mount command returns 0") || BAIL_OUT("");
|
||||||
system("./build/encfs --standard --extpass=\"echo test\" $crypt $mnt 2>&1");
|
|
||||||
ok( $? == 0, "encfs command returns 0") || return;
|
system("./build/encfs --extpass=\"echo test\" $ciphertext $decrypted");
|
||||||
ok(open(OUT , "> $mnt/file"), "write content");
|
ok($? == 0, "encfs tmpfs command returns 0") || BAIL_OUT("");
|
||||||
while(print OUT "0123456789") {}
|
|
||||||
ok ($!{ENOSPC}, "write returned $! instead of ENOSPC");
|
open(OUT, "> $ciphertext/" . encName("mount"));
|
||||||
close OUT;
|
close OUT;
|
||||||
portable_unmount($mnt);
|
ok(waitForFile("$decrypted/mount"), "mount test file exists") || BAIL_OUT("");
|
||||||
system("$sudo_cmd umount $crypt");
|
|
||||||
}
|
ok(open(OUT , "> $decrypted/file"), "write content");
|
||||||
|
while (print OUT "0123456789") {}
|
||||||
|
ok($!{ENOSPC}, "write returned $! instead of ENOSPC");
|
||||||
|
close OUT;
|
||||||
|
|
||||||
|
portable_unmount($decrypted);
|
||||||
|
ok(waitForFile("$decrypted/mount", 5, 1), "mount test file gone") || BAIL_OUT("");
|
||||||
|
system("$sudo_cmd umount $ciphertext");
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ require("integration/common.pl");
|
|||||||
|
|
||||||
my $tempDir = $ENV{'TMPDIR'} || "/tmp";
|
my $tempDir = $ENV{'TMPDIR'} || "/tmp";
|
||||||
|
|
||||||
if($^O eq "linux" and $tempDir eq "/tmp") {
|
if ($^O eq "linux" and $tempDir eq "/tmp") {
|
||||||
# On Linux, /tmp is often a tmpfs mount that does not support
|
# On Linux, /tmp is often a tmpfs mount that does not support
|
||||||
# extended attributes. Use /var/tmp instead.
|
# extended attributes. Use /var/tmp instead.
|
||||||
$tempDir = "/var/tmp";
|
$tempDir = "/var/tmp";
|
||||||
@ -22,19 +22,19 @@ if($^O eq "linux" and $tempDir eq "/tmp") {
|
|||||||
# Find attr binary
|
# Find attr binary
|
||||||
# Linux
|
# Linux
|
||||||
my @binattr = ("attr", "-l");
|
my @binattr = ("attr", "-l");
|
||||||
if(system("which xattr > /dev/null 2>&1") == 0)
|
if (system("which xattr > /dev/null 2>&1") == 0)
|
||||||
{
|
{
|
||||||
# Mac OS X
|
# Mac OS X
|
||||||
@binattr = ("xattr", "-s");
|
@binattr = ("xattr", "-s");
|
||||||
}
|
}
|
||||||
if(system("which lsextattr > /dev/null 2>&1") == 0)
|
if (system("which lsextattr > /dev/null 2>&1") == 0)
|
||||||
{
|
{
|
||||||
# FreeBSD
|
# FreeBSD
|
||||||
@binattr = ("lsextattr", "-h", "user");
|
@binattr = ("lsextattr", "-h", "user");
|
||||||
}
|
}
|
||||||
# Do we support xattr ?
|
# Do we support xattr ?
|
||||||
my $have_xattr = 1;
|
my $have_xattr = 1;
|
||||||
if(system("./build/encfs --verbose --version 2>&1 | grep -q HAVE_XATTR") != 0)
|
if (system("./build/encfs --verbose --version 2>&1 | grep -q HAVE_XATTR") != 0)
|
||||||
{
|
{
|
||||||
$have_xattr = 0;
|
$have_xattr = 0;
|
||||||
}
|
}
|
||||||
@ -76,7 +76,7 @@ sub cleanup
|
|||||||
portable_unmount($ciphertext);
|
portable_unmount($ciphertext);
|
||||||
our $workingDir;
|
our $workingDir;
|
||||||
rmtree($workingDir);
|
rmtree($workingDir);
|
||||||
ok( ! -d $workingDir, "working dir removed");
|
ok(! -d $workingDir, "working dir removed");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Helper function
|
# Helper function
|
||||||
@ -111,7 +111,7 @@ sub copy_test
|
|||||||
# first be sure .encfs6.xml does not show up
|
# first be sure .encfs6.xml does not show up
|
||||||
# We does not use -f for this test, as it would succeed, .encfs6.xml is only hidden from readdir.
|
# We does not use -f for this test, as it would succeed, .encfs6.xml is only hidden from readdir.
|
||||||
my $f = encName(".encfs6.xml");
|
my $f = encName(".encfs6.xml");
|
||||||
cmp_ok( length($f), '>', 8, "encrypted name ok" );
|
cmp_ok(length($f), '>', 8, "encrypted name ok");
|
||||||
ok(system("ls -1 $ciphertext | grep -qwF -- $f") != 0, "configuration file .encfs6.xml not visible in $ciphertext");
|
ok(system("ls -1 $ciphertext | grep -qwF -- $f") != 0, "configuration file .encfs6.xml not visible in $ciphertext");
|
||||||
# copy test
|
# copy test
|
||||||
ok(system("cp -a encfs $plain && mkdir $plain/foo && touch $plain/foo/.encfs6.xml")==0, "copying files to plain");
|
ok(system("cp -a encfs $plain && mkdir $plain/foo && touch $plain/foo/.encfs6.xml")==0, "copying files to plain");
|
||||||
@ -172,7 +172,7 @@ sub grow {
|
|||||||
|
|
||||||
my $ok = 1;
|
my $ok = 1;
|
||||||
my $max = 9000;
|
my $max = 9000;
|
||||||
for($i=5; $i < $max; $i += 5)
|
for ($i=5; $i < $max; $i += 5)
|
||||||
{
|
{
|
||||||
print($pfh "abcde") or die("write failed");
|
print($pfh "abcde") or die("write failed");
|
||||||
# autoflush should make sure the write goes to the kernel
|
# autoflush should make sure the write goes to the kernel
|
||||||
@ -181,7 +181,7 @@ sub grow {
|
|||||||
sizeVerify($cfh, $i) or $ok = 0;
|
sizeVerify($cfh, $i) or $ok = 0;
|
||||||
sizeVerify($dfh, $i) or $ok = 0;
|
sizeVerify($dfh, $i) or $ok = 0;
|
||||||
|
|
||||||
if(md5fh($vfh) ne md5fh($dfh))
|
if (md5fh($vfh) ne md5fh($dfh))
|
||||||
{
|
{
|
||||||
$ok = 0;
|
$ok = 0;
|
||||||
print("# content is different, unified diff:\n");
|
print("# content is different, unified diff:\n");
|
||||||
@ -215,22 +215,22 @@ sub writesDenied {
|
|||||||
writeZeroes($fn, 1024);
|
writeZeroes($fn, 1024);
|
||||||
my $efn = $ciphertext . "/" . encName("writesDenied");
|
my $efn = $ciphertext . "/" . encName("writesDenied");
|
||||||
open(my $fh, ">", $efn);
|
open(my $fh, ">", $efn);
|
||||||
if( ok( $! == EROFS, "open for write denied, EROFS")) {
|
if (ok($! == EROFS, "open for write denied, EROFS")) {
|
||||||
ok( 1, "writing denied, filehandle not open");
|
ok(1, "writing denied, filehandle not open");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
print($fh "foo");
|
print($fh "foo");
|
||||||
ok( $! == EROFS, "writing denied, EROFS");
|
ok($! == EROFS, "writing denied, EROFS");
|
||||||
}
|
}
|
||||||
$target = $ciphertext . "/" . encName("writesDenied2");
|
$target = $ciphertext . "/" . encName("writesDenied2");
|
||||||
rename($efn, $target);
|
rename($efn, $target);
|
||||||
ok( $! == EROFS, "rename denied, EROFS") or die();
|
ok($! == EROFS, "rename denied, EROFS") or die();
|
||||||
unlink($efn);
|
unlink($efn);
|
||||||
ok( $! == EROFS, "unlink denied, EROFS");
|
ok($! == EROFS, "unlink denied, EROFS");
|
||||||
utime(undef, undef, $efn) ;
|
utime(undef, undef, $efn) ;
|
||||||
ok( $! == EROFS, "touch denied, EROFS");
|
ok($! == EROFS, "touch denied, EROFS");
|
||||||
truncate($efn, 10);
|
truncate($efn, 10);
|
||||||
ok( $! == EROFS, "truncate denied, EROFS");
|
ok($! == EROFS, "truncate denied, EROFS");
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup mounts
|
# Setup mounts
|
||||||
|
Loading…
Reference in New Issue
Block a user