mirror of
https://github.com/vgough/encfs.git
synced 2024-11-24 17:03:13 +01:00
add automated test script, along with options to automate filesystem creation
git-svn-id: http://encfs.googlecode.com/svn/trunk@53 db9cf616-1c43-0410-9cb8-a902689de0d6
This commit is contained in:
parent
39bae7bbf5
commit
9ba581ad00
@ -5,6 +5,7 @@ Thu Nov 26 2009 Valient Gough <vgough@pobox.com>
|
||||
* don't enable valgrind support unless explicitly requested.
|
||||
Fix for issue 35.
|
||||
* fix INSTALL instructions. issue 47
|
||||
* add --standard and --paranoia options to automate creation
|
||||
|
||||
Sun Nov 22 2009 Valient Gough <vgough@pobox.com>
|
||||
* use lutimes instead of utimes, so that symlinks can have time modified
|
||||
|
@ -934,7 +934,8 @@ bool selectZeroBlockPassThrough()
|
||||
RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
|
||||
bool enableIdleTracking, bool forceDecode,
|
||||
const std::string &passwordProgram,
|
||||
bool useStdin, bool reverseEncryption )
|
||||
bool useStdin, bool reverseEncryption,
|
||||
ConfigMode configMode)
|
||||
{
|
||||
RootPtr rootInfo;
|
||||
|
||||
@ -943,16 +944,19 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
|
||||
// xgroup(setup)
|
||||
cout << _("Creating new encrypted volume.") << endl;
|
||||
|
||||
// xgroup(setup)
|
||||
cout << _("Please choose from one of the following options:\n"
|
||||
" enter \"x\" for expert configuration mode,\n"
|
||||
" enter \"p\" for pre-configured paranoia mode,\n"
|
||||
" anything else, or an empty line will select standard mode.\n"
|
||||
"?> ");
|
||||
|
||||
char answer[10] = {0};
|
||||
fgets( answer, sizeof(answer), stdin );
|
||||
cout << "\n";
|
||||
if(configMode == Config_Prompt)
|
||||
{
|
||||
// xgroup(setup)
|
||||
cout << _("Please choose from one of the following options:\n"
|
||||
" enter \"x\" for expert configuration mode,\n"
|
||||
" enter \"p\" for pre-configured paranoia mode,\n"
|
||||
" anything else, or an empty line will select standard mode.\n"
|
||||
"?> ");
|
||||
|
||||
fgets( answer, sizeof(answer), stdin );
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
int keySize = 0;
|
||||
int blockSize = 0;
|
||||
@ -975,7 +979,7 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
|
||||
blockMACRandBytes = 0;
|
||||
}
|
||||
|
||||
if(answer[0] == 'p')
|
||||
if(configMode == Config_Paranoia || answer[0] == 'p')
|
||||
{
|
||||
if (reverseEncryption)
|
||||
{
|
||||
@ -1000,8 +1004,7 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
|
||||
chainedIV = true;
|
||||
externalIV = true;
|
||||
desiredKDFDuration = ParanoiaKDFDuration;
|
||||
} else
|
||||
if(answer[0] != 'x')
|
||||
} else if(configMode == Config_Standard || answer[0] != 'x')
|
||||
{
|
||||
// xgroup(setup)
|
||||
cout << _("Standard configuration selected.") << "\n";
|
||||
@ -1565,7 +1568,7 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
|
||||
}
|
||||
}
|
||||
|
||||
// first, instanciate the cipher.
|
||||
// first, instanciate the cipher.
|
||||
shared_ptr<Cipher> cipher = config.getCipher();
|
||||
if(!cipher)
|
||||
{
|
||||
@ -1649,7 +1652,7 @@ RootPtr initFS( EncFS_Context *ctx, const shared_ptr<EncFS_Opts> &opts )
|
||||
// creating a new encrypted filesystem
|
||||
rootInfo = createV6Config( ctx, opts->rootDir, opts->idleTracking,
|
||||
opts->forceDecode, opts->passwordProgram, opts->useStdin,
|
||||
opts->reverseEncryption );
|
||||
opts->reverseEncryption, opts->configMode );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,6 +142,12 @@ ConfigType readConfig( const std::string &rootDir, EncFSConfig *config );
|
||||
bool saveConfig( ConfigType type, const std::string &rootdir,
|
||||
EncFSConfig *config );
|
||||
|
||||
enum ConfigMode
|
||||
{
|
||||
Config_Prompt,
|
||||
Config_Standard,
|
||||
Config_Paranoia
|
||||
};
|
||||
|
||||
struct EncFS_Opts
|
||||
{
|
||||
@ -159,6 +165,9 @@ struct EncFS_Opts
|
||||
bool ownerCreate; // set owner of new files to caller
|
||||
|
||||
bool reverseEncryption; // Reverse encryption
|
||||
|
||||
ConfigMode configMode;
|
||||
|
||||
EncFS_Opts()
|
||||
{
|
||||
createIfNotFound = true;
|
||||
@ -169,6 +178,7 @@ struct EncFS_Opts
|
||||
useStdin = false;
|
||||
ownerCreate = false;
|
||||
reverseEncryption = false;
|
||||
configMode = Config_Prompt;
|
||||
}
|
||||
};
|
||||
|
||||
@ -180,7 +190,7 @@ RootPtr createV6Config( EncFS_Context *ctx, const std::string &rootDir,
|
||||
bool enableIdleTracking,
|
||||
bool forceDecode,
|
||||
const std::string &passwordProgram, bool reverseEncryption,
|
||||
bool allowHoles );
|
||||
bool allowHoles, ConfigMode mode );
|
||||
|
||||
|
||||
void showFSInfo( const EncFSConfig &config );
|
||||
|
@ -144,3 +144,9 @@ encfs-man.html: encfs.pod
|
||||
@POD2HTML@ encfs.pod > $@
|
||||
endif
|
||||
|
||||
tests:
|
||||
perl -MTest::Harness -e '$$Test::Harness::verbose=0; runtests @ARGV;' *.t
|
||||
|
||||
tests-verbose:
|
||||
perl -MTest::Harness -e '$$Test::Harness::verbose=1; runtests @ARGV;' *.t
|
||||
|
||||
|
@ -19,7 +19,8 @@ B<encfs> [B<--version>] [B<-s>] [B<-f>] [B<-v>|B<--verbose>]
|
||||
[B<-i MINUTES>|B<--idle=MINUTES>] [B<--extpass=program>]
|
||||
[B<-S>|B<--stdinpass>] [B<--anykey>] [B<--forcedecode>]
|
||||
[B<-d>|B<--fuse-debug>] [B<--public>] [B<--no-default-flags>]
|
||||
[B<--ondemand>] [B<--reverse>] [B<-o FUSE_OPTION>]
|
||||
[B<--ondemand>] [B<--reverse>] [B<--standard>]
|
||||
[B<-o FUSE_OPTION>]
|
||||
I<rootdir> I<mountPoint>
|
||||
[B<--> [I<Fuse Mount Options>]]
|
||||
|
||||
@ -138,6 +139,15 @@ Now /tmp/plain-view contains the same data as /home/me
|
||||
Note that B<--reverse> mode only works with limited configuration options, so
|
||||
many settings may be disabled when used.
|
||||
|
||||
=item B<--standard>
|
||||
|
||||
If creating a new filesystem, this automatically selects standard configuration
|
||||
options, to help with automatic filesystem creation. This is the set of
|
||||
options that should be used unless you know what you're doing and have read the
|
||||
documentation.
|
||||
|
||||
When not creating a filesystem, this flag does nothing.
|
||||
|
||||
=item B<-o FUSE_ARG>
|
||||
|
||||
Pass through B<FUSE> args to the underlying library. This makes it easy to
|
||||
|
@ -226,6 +226,8 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
|
||||
{"verbose", 0, 0, 'v'}, // verbose mode
|
||||
{"version", 0, 0, 'V'}, //version
|
||||
{"reverse", 0, 0, 'r'}, // reverse encryption
|
||||
{"standard", 0, 0, '1'}, // standard configuration
|
||||
{"paranoia", 0, 0, '2'}, // standard configuration
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
@ -249,6 +251,12 @@ bool processArgs(int argc, char *argv[], const shared_ptr<EncFS_Args> &out)
|
||||
|
||||
switch( res )
|
||||
{
|
||||
case '1':
|
||||
out->opts->configMode = Config_Standard;
|
||||
break;
|
||||
case '2':
|
||||
out->opts->configMode = Config_Paranoia;
|
||||
break;
|
||||
case 's':
|
||||
out->isThreaded = false;
|
||||
break;
|
||||
@ -523,7 +531,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
encfs_oper.getattr = encfs_getattr;
|
||||
encfs_oper.readlink = encfs_readlink;
|
||||
encfs_oper.getdir = encfs_getdir;
|
||||
encfs_oper.getdir = encfs_getdir; // deprecated for readdir
|
||||
encfs_oper.mknod = encfs_mknod;
|
||||
encfs_oper.mkdir = encfs_mkdir;
|
||||
encfs_oper.unlink = encfs_unlink;
|
||||
@ -534,7 +542,7 @@ int main(int argc, char *argv[])
|
||||
encfs_oper.chmod = encfs_chmod;
|
||||
encfs_oper.chown = encfs_chown;
|
||||
encfs_oper.truncate = encfs_truncate;
|
||||
encfs_oper.utime = encfs_utime;
|
||||
encfs_oper.utime = encfs_utime; // deprecated for utimens
|
||||
encfs_oper.open = encfs_open;
|
||||
encfs_oper.read = encfs_read;
|
||||
encfs_oper.write = encfs_write;
|
||||
@ -558,9 +566,22 @@ int main(int argc, char *argv[])
|
||||
//encfs_oper.create = encfs_create;
|
||||
encfs_oper.ftruncate = encfs_ftruncate;
|
||||
encfs_oper.fgetattr = encfs_fgetattr;
|
||||
//encfs_oper.lock = encfs_lock;
|
||||
encfs_oper.utimens = encfs_utimens;
|
||||
//encfs_oper.bmap = encfs_bmap;
|
||||
|
||||
#if (__FreeBSD__ >= 10)
|
||||
// encfs_oper.setvolname
|
||||
// encfs_oper.exchange
|
||||
// encfs_oper.getxtimes
|
||||
// encfs_oper.setbkuptime
|
||||
// encfs_oper.setchgtime
|
||||
// encfs_oper.setcrtime
|
||||
// encfs_oper.chflags
|
||||
// encfs_oper.setattr_x
|
||||
// encfs_oper.fsetattr_x
|
||||
#endif
|
||||
|
||||
openssl_init( encfsArgs->isThreaded );
|
||||
|
||||
// context is not a smart pointer because it will live for the life of
|
||||
|
213
encfs/tests.t
Normal file
213
encfs/tests.t
Normal file
@ -0,0 +1,213 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use Test::More qw( no_plan );
|
||||
use File::Path;
|
||||
use IO::Handle;
|
||||
use Digest::MD5;
|
||||
|
||||
my $tempDir = $ENV{'TMPDIR'} || "/tmp";
|
||||
|
||||
my $raw = "$tempDir/crypt-raw-$$";
|
||||
my $crypt = "$tempDir/crypt-$$";
|
||||
|
||||
|
||||
# test filesystem in standard config mode
|
||||
&runTests('standard');
|
||||
|
||||
# test in paranoia mode
|
||||
&runTests('paranoia');
|
||||
|
||||
|
||||
|
||||
sub runTests
|
||||
{
|
||||
my $mode = shift;
|
||||
|
||||
my $hardlinks = 1;
|
||||
if($mode eq 'standard')
|
||||
{
|
||||
&mount("--standard");
|
||||
} elsif($mode eq 'paranoia')
|
||||
{
|
||||
&mount("--paranoia");
|
||||
$hardlinks = 0; # no hardlinks in paranoia mode
|
||||
} else
|
||||
{
|
||||
die "invalid test mode";
|
||||
}
|
||||
|
||||
# tests..
|
||||
&fileCreation;
|
||||
&links($hardlinks);
|
||||
&truncate;
|
||||
&renames;
|
||||
|
||||
&cleanup;
|
||||
}
|
||||
|
||||
sub renames
|
||||
{
|
||||
ok( open(F, ">$crypt/orig-name") && close F, "create file for rename test");
|
||||
ok( -f "$crypt/orig-name", "file exists");
|
||||
|
||||
ok( rename("$crypt/orig-name", "$crypt/2nd-name"), "rename");
|
||||
ok( ! -f "$crypt/orig-name", "file exists");
|
||||
ok( -f "$crypt/2nd-name", "file exists");
|
||||
|
||||
# rename directory with contents
|
||||
ok( mkpath("$crypt/orig-dir/foo"), "mkdir for rename test");
|
||||
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");
|
||||
}
|
||||
|
||||
sub truncate
|
||||
{
|
||||
# write to file, then truncate it
|
||||
ok( open(OUT, "+> $crypt/trunc"), "create truncate-test file");
|
||||
autoflush OUT 1;
|
||||
print OUT "12345678901234567890";
|
||||
|
||||
is( -s "$crypt/trunc", 20, "initial file size" );
|
||||
|
||||
ok( truncate(OUT, 10), "truncate" );
|
||||
|
||||
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");
|
||||
|
||||
seek(OUT, 0, 0);
|
||||
is( Digest::MD5->new->addfile(*OUT)->hexdigest,
|
||||
"5f170cc34b1944d75d86cc01496292df", "content digest");
|
||||
|
||||
# try crossing block boundaries
|
||||
seek(OUT, 10000,0);
|
||||
print OUT "abcde";
|
||||
seek(OUT, 0, 0);
|
||||
is( Digest::MD5->new->addfile(*OUT)->hexdigest,
|
||||
"117a51c980b64dcd21df097d02206f98", "content digest");
|
||||
|
||||
# then truncate back to 35 chars
|
||||
truncate(OUT, 35);
|
||||
seek(OUT, 0, 0);
|
||||
is( Digest::MD5->new->addfile(*OUT)->hexdigest,
|
||||
"5f170cc34b1944d75d86cc01496292df", "content digest");
|
||||
|
||||
close OUT;
|
||||
}
|
||||
|
||||
sub fileCreation
|
||||
{
|
||||
# create a file
|
||||
qx(df -ah > "$crypt/df.txt");
|
||||
ok( -f "$crypt/df.txt", "file created" );
|
||||
|
||||
# ensure there is an encrypted version.
|
||||
my $c = qx(./encfsctl encode --extpass="echo test" $raw df.txt);
|
||||
chomp($c);
|
||||
cmp_ok( length($c), '>', 8, "encrypted name ok" );
|
||||
ok( -f "$raw/$c", "encrypted file created" );
|
||||
|
||||
# check contents
|
||||
my $count = qx(grep -c crypt-$$ "$crypt/df.txt");
|
||||
isnt(scalar($count), 0, "encrypted file readable");
|
||||
|
||||
unlink "$crypt/df.txt";
|
||||
ok( ! -f "$crypt/df.txt", "file removal" );
|
||||
ok( ! -f "$raw/$c", "file removal" );
|
||||
}
|
||||
|
||||
sub checkContents
|
||||
{
|
||||
my ($file, $expected, $testName) = @_;
|
||||
|
||||
open(IN, "< $file");
|
||||
my $line = <IN>;
|
||||
is( $line, $expected, $testName );
|
||||
|
||||
close IN;
|
||||
}
|
||||
|
||||
sub links
|
||||
{
|
||||
my $hardlinkTests = shift;
|
||||
|
||||
my $contents = "hello world\n";
|
||||
ok( open(OUT, "> $crypt/data"), "create file for link test" );
|
||||
print OUT $contents;
|
||||
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" unless $hardlinkTests;
|
||||
|
||||
ok( link("$crypt/data", "$crypt/data.2"), "hard link");
|
||||
checkContents("$crypt/data.2", $contents, "hardlink read");
|
||||
};
|
||||
}
|
||||
|
||||
sub mount
|
||||
{
|
||||
my $args = shift;
|
||||
|
||||
ok( ! -d $raw, "no existing dir");
|
||||
ok( ! -d $crypt, "no existing dir");
|
||||
|
||||
mkdir $raw;
|
||||
ok( -d $raw, "created dir" );
|
||||
mkdir $crypt;
|
||||
ok( -d $crypt, "created dir" );
|
||||
|
||||
qx(./encfs --extpass="echo test" $args $raw $crypt);
|
||||
|
||||
ok( -f "$raw/.encfs6.xml", "created control file");
|
||||
}
|
||||
|
||||
sub cleanup
|
||||
{
|
||||
my $fusermount = qx(which fusermount);
|
||||
if(-f $fusermount)
|
||||
{
|
||||
qx($fusermount -u "$crypt");
|
||||
} else
|
||||
{
|
||||
qx(umount "$crypt");
|
||||
}
|
||||
|
||||
rmdir $crypt;
|
||||
ok( ! -d $crypt, "unmount ok, mount point removed");
|
||||
|
||||
if(-d $raw)
|
||||
{
|
||||
rmtree($raw);
|
||||
}
|
||||
ok( ! -d $raw, "encrypted directory removed");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user