First pass at adding key files
This commit is contained in:
199
site/slowtwitch.com/cgi-bin/articles/GT/TempFile.pm
Normal file
199
site/slowtwitch.com/cgi-bin/articles/GT/TempFile.pm
Normal file
@ -0,0 +1,199 @@
|
||||
# ==================================================================
|
||||
# Gossamer Threads Module Library - http://gossamer-threads.com/
|
||||
#
|
||||
# GT::TempFile
|
||||
# Author : Scott Beck
|
||||
# CVS Info : 087,071,086,086,085
|
||||
# $Id: TempFile.pm,v 1.36 2005/03/23 04:27:26 jagerman Exp $
|
||||
#
|
||||
# Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
||||
# ==================================================================
|
||||
#
|
||||
# Description:
|
||||
# Implements a tempfile.
|
||||
#
|
||||
|
||||
package GT::TempFile;
|
||||
# ===================================================================
|
||||
|
||||
# Pragmas
|
||||
use strict;
|
||||
use vars qw/$VERSION $TMP_DIR %OBJECTS/;
|
||||
use bases 'GT::Base' => ':all';
|
||||
use overload '""' => \&as_string;
|
||||
|
||||
$VERSION = sprintf "%d.%03d", q$Revision: 1.36 $ =~ /(\d+)\.(\d+)/;
|
||||
|
||||
sub find_tmpdir {
|
||||
# -------------------------------------------------------------------
|
||||
# Sets the tmpdir.
|
||||
#
|
||||
return $TMP_DIR if $TMP_DIR;
|
||||
my @tmp_dirs;
|
||||
for (qw/GT_TMPDIR TEMP TMP TMPDIR/) {
|
||||
push @tmp_dirs, $ENV{$_} if exists $ENV{$_};
|
||||
}
|
||||
push @tmp_dirs, $ENV{windir} . '/temp' if exists $ENV{windir};
|
||||
eval { push @tmp_dirs, (getpwuid $>)[7] . '/tmp' };
|
||||
push @tmp_dirs, '/usr/tmp', '/var/tmp', 'c:/temp', '/tmp', '/temp', '/sys$scratch', '/WWW_ROOT', 'c:/windows/temp', 'c:/winnt/temp';
|
||||
|
||||
for my $dir (@tmp_dirs) {
|
||||
return $TMP_DIR = $dir if $dir and -d $dir and -w _ and -x _;
|
||||
}
|
||||
$TMP_DIR = '.';
|
||||
}
|
||||
|
||||
sub new {
|
||||
# -----------------------------------------------------------------------------
|
||||
# Create a new tempfile.
|
||||
#
|
||||
$TMP_DIR ||= find_tmpdir();
|
||||
my $self = bless {}, 'GT::TempFile::Tmp';
|
||||
$self->reset;
|
||||
|
||||
# Backwards compatibility
|
||||
if ( @_ == 2 and not ref( $_[1] ) ) {
|
||||
( $self->{tmp_dir} ) = $_[1];
|
||||
}
|
||||
elsif ( @_ > 1 ) {
|
||||
$self->set( @_[1 .. $#_] );
|
||||
}
|
||||
|
||||
my $dir = $self->{tmp_dir} || $TMP_DIR;
|
||||
my $count = substr(time, -4) . int(rand(10000));
|
||||
my $filename = '';
|
||||
|
||||
# Directory for locking
|
||||
my $lock_dir = "$dir/$self->{prefix}GT_TempFile_lock";
|
||||
|
||||
# W need to create the directory
|
||||
my $safety = 0;
|
||||
until ( mkdir( $lock_dir, 0777 ) ) {
|
||||
|
||||
# If we wait 10 seconds and still no lock we assume the lockfile is stale
|
||||
if ( $safety++ > 10 ) {
|
||||
rmdir $lock_dir or $self->fatal( 'RMDIR', $lock_dir, "$!" );
|
||||
}
|
||||
sleep 1;
|
||||
}
|
||||
|
||||
# Now lets get our temp file
|
||||
for (1 .. 20) {
|
||||
$filename = "$dir/$self->{prefix}GTTemp$count";
|
||||
last if (! -f $filename);
|
||||
$count++;
|
||||
}
|
||||
|
||||
# If the open fails we need to remove the lockdir
|
||||
if ( !open( FH, ">$filename" ) ) {
|
||||
rmdir $lock_dir or $self->fatal( 'RMDIR', $lock_dir, "$!" );
|
||||
$self->fatal( 'WRITEOPEN', $filename, "$!" );
|
||||
}
|
||||
close FH;
|
||||
|
||||
# All done searching for a temp file, now release the directory lock
|
||||
rmdir $lock_dir or $self->fatal( 'RMDIR', $lock_dir, "$!" );
|
||||
($filename =~ /^(.+)$/) and ($filename = $1); # Detaint.
|
||||
|
||||
$self->{filename} = $filename;
|
||||
my $object = bless \$filename, 'GT::TempFile';
|
||||
$OBJECTS{overload::StrVal $object} = $self;
|
||||
$self->debug("New tmpfile created ($filename).") if ($self->{_debug});
|
||||
$object;
|
||||
}
|
||||
|
||||
sub as_string {
|
||||
# -------------------------------------------------------------------
|
||||
# Backwards compatibility
|
||||
my ( $self ) = @_;
|
||||
return $$self;
|
||||
}
|
||||
|
||||
sub DESTROY {
|
||||
# -------------------------------------------------------------------
|
||||
my $obj = shift;
|
||||
my $self = $OBJECTS{$obj};
|
||||
$self->debug("Deleteing $self->{filename}") if $self->{_debug};
|
||||
|
||||
# unlink the file if they wanted it deleted
|
||||
if ($self->{destroy}) {
|
||||
unless (unlink $self->{filename}) {
|
||||
$self->debug("Unable to remove temp file: $self->{filename} ($!)") if $self->{_debug};
|
||||
}
|
||||
}
|
||||
delete $OBJECTS{$obj};
|
||||
}
|
||||
|
||||
package GT::TempFile::Tmp;
|
||||
use bases 'GT::Base' => '';
|
||||
use vars qw/$ATTRIBS $ERRORS/;
|
||||
$ATTRIBS = {
|
||||
prefix => '',
|
||||
destroy => 1,
|
||||
tmp_dir => undef,
|
||||
};
|
||||
$ERRORS = { SAFETY => "Safety reached while trying to create lock directory %s, (%s)" };
|
||||
|
||||
1;
|
||||
|
||||
__END__
|
||||
|
||||
=head1 NAME
|
||||
|
||||
GT::TempFile - implements a very simple temp file.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $file = new GT::TempFile;
|
||||
open (FILE, "> $file");
|
||||
print FILE "somedata";
|
||||
close FILE;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
GT::TempFile implements a very simple temp file system that will remove
|
||||
itself once the variable goes out of scope.
|
||||
|
||||
When you call new, it creates a random file name and looks for a
|
||||
tmp directory. What you get back is an object that when dereferenced
|
||||
is the file name. You can also pass in a temp dir to use:
|
||||
|
||||
my $file = new GT::Tempfile '/path/to/tmpfiles';
|
||||
|
||||
Other option you may use are:
|
||||
my $file = new GT::TempFile(
|
||||
destroy => 1,
|
||||
prefix => '',
|
||||
tmp_dir => '/tmp'
|
||||
);
|
||||
|
||||
|
||||
When the object is destroyed, it automatically unlinks the temp file
|
||||
unless you specify I<destroy> => 0.
|
||||
|
||||
I<prefix> will be prepended to the start of all temp files created
|
||||
and the lock directory that is created. It is used to keep programs
|
||||
using the tempfile module that do not have the temp files destroyed
|
||||
from clashing.
|
||||
|
||||
I<tmp_dir> is the same as calling new with just one argument, it is
|
||||
the directory where files will be stored.
|
||||
|
||||
TempFile picks a temp directory based on the following:
|
||||
|
||||
1. ENV{GT_TMPDIR}
|
||||
2. ~/tmp
|
||||
3. ENV{TMPDIR}, ENV{TEMP}, ENV{TMP}
|
||||
4. /usr/tmp, /var/tmp, c:/temp, /tmp, /temp,
|
||||
/WWW_ROOT, c:/windows/temp, c:/winnt/temp
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved.
|
||||
http://www.gossamer-threads.com/
|
||||
|
||||
=head1 VERSION
|
||||
|
||||
Revision: $Id: TempFile.pm,v 1.36 2005/03/23 04:27:26 jagerman Exp $
|
||||
|
||||
=cut
|
Reference in New Issue
Block a user