Abstracted spool_dir creation and added temp_file() and temp_dir() subs to
make it easier for plugins to manage temporary workspace. Also add POD and tests for the new functions. Still need to add tests to the temp_*() calls from a plugin. git-svn-id: https://svn.perl.org/qpsmtpd/trunk@369 958fd67b-6ff1-0310-b445-bb7760255be9
This commit is contained in:
parent
d790bd519d
commit
bb36c60b6a
7
Changes
7
Changes
@ -1,6 +1,13 @@
|
|||||||
|
|
||||||
0.29
|
0.29
|
||||||
|
|
||||||
|
New temp_file() and temp_dir() methods; when used by plugins, they create
|
||||||
|
a filename or directory which will last only as long as the current
|
||||||
|
transaction. Also created a spool_dir() method which checks/creates the
|
||||||
|
spool_dir when the application starts up. All three methods are also
|
||||||
|
available in the base class where the temp_* objects are not automatically
|
||||||
|
limited to the transaction's lifetime. (John Peacock)
|
||||||
|
|
||||||
Added Gavin Carr's greylisting plugin
|
Added Gavin Carr's greylisting plugin
|
||||||
|
|
||||||
Renamed config/ to config.sample/
|
Renamed config/ to config.sample/
|
||||||
|
@ -200,3 +200,32 @@ With the $Include stuff you order using the filename of the plugin.d
|
|||||||
file. So if you have a plugin called xyz but want it to come early on,
|
file. So if you have a plugin called xyz but want it to come early on,
|
||||||
you call it's config file 00_xyz, but that file still refers to the
|
you call it's config file 00_xyz, but that file still refers to the
|
||||||
plugin called xyz.
|
plugin called xyz.
|
||||||
|
|
||||||
|
=head1 Temporary Files
|
||||||
|
|
||||||
|
The temporary file and directory functions can be used for plugin specific
|
||||||
|
workfiles and will automatically be deleted at the end of the current
|
||||||
|
transaction.
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item temp_file()
|
||||||
|
|
||||||
|
Returns a unique name of a file located in the default spool directory, but
|
||||||
|
does not open that file (i.e. it is the name not a file handle).
|
||||||
|
|
||||||
|
=item temp_dir()
|
||||||
|
|
||||||
|
Returns the name of a unique directory located in the default spool
|
||||||
|
directory, after creating the directory with 0700 rights. If you need a
|
||||||
|
directory with different rights (say for an antivirus daemon), you will
|
||||||
|
need to use the base function $self->qp->temp_dir() which takes a single
|
||||||
|
parameter for the permissions requested (see L<mkdir> for details). A
|
||||||
|
directory created like this will B<not> be deleted when the transaction is
|
||||||
|
ended.
|
||||||
|
|
||||||
|
=item spool_dir()
|
||||||
|
|
||||||
|
Returns the configured system-wide spool directory.
|
||||||
|
|
||||||
|
=back
|
||||||
|
@ -255,4 +255,52 @@ sub _register_hook {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub spool_dir {
|
||||||
|
my $self = shift;
|
||||||
|
|
||||||
|
unless ( $self->{_spool_dir} ) { # first time through
|
||||||
|
my $spool_dir = $self->config('spool_dir')
|
||||||
|
|| Qpsmtpd::Utils::tildeexp('~/tmp/');
|
||||||
|
|
||||||
|
$spool_dir .= "/" unless ($spool_dir =~ m!/$!);
|
||||||
|
|
||||||
|
$spool_dir =~ /^(.+)$/ or die "spool_dir not configured properly";
|
||||||
|
$spool_dir = $1; # cleanse the taint
|
||||||
|
$self->{_spool_dir} = $spool_dir;
|
||||||
|
|
||||||
|
# Make sure the spool dir has appropriate rights
|
||||||
|
if (-e $spool_dir) {
|
||||||
|
my $mode = (stat($spool_dir))[2];
|
||||||
|
warn "Permissions on spool_dir $spool_dir are not 0700" if $mode & 07077;
|
||||||
|
}
|
||||||
|
|
||||||
|
# And finally, create it if it doesn't already exist
|
||||||
|
-d $spool_dir or mkdir($spool_dir, 0700)
|
||||||
|
or die "Could not create spool_dir $spool_dir: $!";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $self->{_spool_dir};
|
||||||
|
}
|
||||||
|
|
||||||
|
# For unique filenames. We write to a local tmp dir so we don't need
|
||||||
|
# to make them unpredictable.
|
||||||
|
my $transaction_counter = 0;
|
||||||
|
|
||||||
|
sub temp_file {
|
||||||
|
my $self = shift;
|
||||||
|
my $filename = $self->spool_dir()
|
||||||
|
. join(":", time, $$, $transaction_counter++);
|
||||||
|
$filename =~ tr!A-Za-z0-9:/_-!!cd;
|
||||||
|
return $filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub temp_dir {
|
||||||
|
my $self = shift;
|
||||||
|
my $mask = shift || 0700;
|
||||||
|
my $dirname = $self->temp_file();
|
||||||
|
-d $dirname or mkdir($dirname, $mask)
|
||||||
|
or die "Could not create temporary directory $dirname: $!";
|
||||||
|
return $dirname;
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -53,6 +53,24 @@ sub connection {
|
|||||||
shift->qp->connection;
|
shift->qp->connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub spool_dir {
|
||||||
|
shift->qp->spool_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub temp_file {
|
||||||
|
my $self = shift;
|
||||||
|
my $tempfile = $self->qp->temp_file;
|
||||||
|
push @{$self->qp->transaction->{_temp_files}}, $tempfile;
|
||||||
|
return $tempfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub temp_dir {
|
||||||
|
my $self = shift;
|
||||||
|
my $tempdir = $self->qp->temp_dir();
|
||||||
|
push @{$self->qp->transaction->{_temp_dirs}}, $tempdir;
|
||||||
|
return $tempdir;
|
||||||
|
}
|
||||||
|
|
||||||
# plugin inheritance:
|
# plugin inheritance:
|
||||||
# usage:
|
# usage:
|
||||||
# sub register {
|
# sub register {
|
||||||
|
@ -7,10 +7,6 @@ use Qpsmtpd::Constants;
|
|||||||
|
|
||||||
use IO::File qw(O_RDWR O_CREAT);
|
use IO::File qw(O_RDWR O_CREAT);
|
||||||
|
|
||||||
# For unique filenames. We write to a local tmp dir so we don't need
|
|
||||||
# to make them unpredictable.
|
|
||||||
my $transaction_counter = 0;
|
|
||||||
|
|
||||||
sub new { start(@_) }
|
sub new { start(@_) }
|
||||||
|
|
||||||
sub start {
|
sub start {
|
||||||
@ -71,22 +67,7 @@ sub body_write {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $data = shift;
|
my $data = shift;
|
||||||
unless ($self->{_body_file}) {
|
unless ($self->{_body_file}) {
|
||||||
my $spool_dir = $self->config('spool_dir') ? $self->config('spool_dir')
|
$self->{_filename} = $self->temp_file();
|
||||||
: Qpsmtpd::Utils::tildeexp('~/tmp/');
|
|
||||||
|
|
||||||
$spool_dir .= "/" unless ($spool_dir =~ m!/$!);
|
|
||||||
|
|
||||||
$spool_dir =~ /^(.+)$/ or die "spool_dir not configured properly";
|
|
||||||
$spool_dir = $1;
|
|
||||||
|
|
||||||
if (-e $spool_dir) {
|
|
||||||
my $mode = (stat($spool_dir))[2];
|
|
||||||
die "Permissions on spool_dir $spool_dir are not 0700" if $mode & 07077;
|
|
||||||
}
|
|
||||||
|
|
||||||
-d $spool_dir or mkdir($spool_dir, 0700) or die "Could not create spool_dir $spool_dir: $!";
|
|
||||||
$self->{_filename} = $spool_dir . join(":", time, $$, $transaction_counter++);
|
|
||||||
$self->{_filename} =~ tr!A-Za-z0-9:/_-!!cd;
|
|
||||||
$self->{_body_file} = IO::File->new($self->{_filename}, O_RDWR|O_CREAT, 0600)
|
$self->{_body_file} = IO::File->new($self->{_filename}, O_RDWR|O_CREAT, 0600)
|
||||||
or die "Could not open file $self->{_filename} - $! "; # . $self->{_body_file}->error;
|
or die "Could not open file $self->{_filename} - $! "; # . $self->{_body_file}->error;
|
||||||
}
|
}
|
||||||
@ -129,6 +110,25 @@ sub DESTROY {
|
|||||||
if ($self->{_filename} and -e $self->{_filename}) {
|
if ($self->{_filename} and -e $self->{_filename}) {
|
||||||
unlink $self->{_filename} or $self->log(LOGERROR, "Could not unlink ", $self->{_filename}, ": $!");
|
unlink $self->{_filename} or $self->log(LOGERROR, "Could not unlink ", $self->{_filename}, ": $!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# These may not exist
|
||||||
|
if ( $self->{_temp_files} ) {
|
||||||
|
$self->log(LOGDEBUG, "Cleaning up temporary transaction files");
|
||||||
|
foreach my $file ( @{$self->{_temp_files}} ) {
|
||||||
|
next unless -e $file;
|
||||||
|
unlink $file or $self->log(LOGERROR,
|
||||||
|
"Could not unlink temporary file", $file, ": $!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Ditto
|
||||||
|
if ( $self->{_temp_dirs} ) {
|
||||||
|
eval {use File::Path};
|
||||||
|
$self->log(LOGDEBUG, "Cleaning up temporary directories");
|
||||||
|
foreach my $dir ( @{$self->{_temp_dirs}} ) {
|
||||||
|
rmtree($dir) or $self->log(LOGERROR,
|
||||||
|
"Could not unlink temporary dir", $dir, ": $!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
27
t/tempstuff.t
Normal file
27
t/tempstuff.t
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/perl -w
|
||||||
|
use Test::More qw(no_plan);
|
||||||
|
use File::Path;
|
||||||
|
use strict;
|
||||||
|
use lib 't';
|
||||||
|
use_ok('Test::Qpsmtpd');
|
||||||
|
|
||||||
|
BEGIN { # need this to happen before anything else
|
||||||
|
my $cwd = `pwd`;
|
||||||
|
chomp($cwd);
|
||||||
|
open my $spooldir, '>', "./config.sample/spool_dir";
|
||||||
|
print $spooldir "$cwd/t/tmp";
|
||||||
|
close $spooldir;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok(my ($smtpd, $conn) = Test::Qpsmtpd->new_conn(), "get new connection");
|
||||||
|
|
||||||
|
my ($spool_dir,$tempfile,$tempdir) = ( $smtpd->spool_dir,
|
||||||
|
$smtpd->temp_file(), $smtpd->temp_dir() );
|
||||||
|
|
||||||
|
ok( $spool_dir =~ m!t/tmp/$!, "Located the spool directory");
|
||||||
|
ok( $tempfile =~ /^$spool_dir/, "Temporary filename" );
|
||||||
|
ok( $tempdir =~ /^$spool_dir/, "Temporary directory" );
|
||||||
|
ok( -d $tempdir, "And that directory exists" );
|
||||||
|
|
||||||
|
unlink "./config.sample/spool_dir";
|
||||||
|
rmtree($spool_dir);
|
Loading…
Reference in New Issue
Block a user