Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > creating a temporary directory

Reply
Thread Tools

creating a temporary directory

 
 
Wybo Dekker
Guest
Posts: n/a
 
      04-02-2005
I would like to create a temporary directory that disappears
after exit (analogous to Tempfile). But ruby doesn't seem to have a
Tempdir class?
(Dir.tmpdir only points to a system tempdir, that should not
disappear of course.)

--
Wybo


 
Reply With Quote
 
 
 
 
nobu.nokada@softhome.net
Guest
Posts: n/a
 
      04-02-2005
Hi,

At Sat, 2 Apr 2005 18:26:51 +0900,
Wybo Dekker wrote in [ruby-talk:136465]:
> I would like to create a temporary directory that disappears
> after exit (analogous to Tempfile). But ruby doesn't seem to have a
> Tempdir class?


Once I had proposed it at [ruby-dev:21336], and this is the
patch for latest version.


Index: lib/tempfile.rb
================================================== =================
RCS file: /cvs/ruby/src/ruby/lib/tempfile.rb,v
retrieving revision 1.27
diff -U2 -p -r1.27 tempfile.rb
--- lib/tempfile.rb 15 Nov 2004 16:45:02 -0000 1.27
+++ lib/tempfile.rb 16 Nov 2004 01:31:27 -0000
@@ -8,19 +8,16 @@ require 'delegate'
require 'tmpdir'

-# A class for managing temporary files. This library is written to be
-# thread safe.
-class Tempfile < DelegateClass(File)
+module AutoRemoval
MAX_TRY = 10
@@cleanlist = []

- # Creates a temporary file of mode 0600 in the temporary directory
- # whose name is basename.pid.n and opens with mode "w+". A Tempfile
- # object works just like a File object.
- #
- # If tmpdir is omitted, the temporary directory is determined by
- # Dir::tmpdir provided by 'tmpdir.rb'.
- # When $SAFE > 0 and the given tmpdir is tainted, it uses
- # /tmp. (Note that ENV values are tainted by default)
- def initialize(basename, tmpdir=Dir::tmpdir)
+ private
+
+ def make_tmpname(basename, n)
+ sprintf('%s%d.%d', basename, $$, n)
+ end
+ private :make_tmpname
+
+ def createtmp(basename, tmpdir=Dir::tmpdir) # :nodoc:
if $SAFE > 0 and tmpdir.tainted?
tmpdir = '/tmp'
@@ -29,17 +26,13 @@ class Tempfile < DelegateClass(File)
lock = nil
n = failure = 0
-
+
begin
Thread.critical = true
-
begin
- tmpname = File.join(tmpdir, make_tmpname(basename, n))
- lock = tmpname + '.lock'
- n += 1
- end while @@cleanlist.include?(tmpname) or
- File.exist?(lock) or File.exist?(tmpname)
-
- Dir.mkdir(lock)
+ tmpname = File.join(tmpdir, make_tmpname(basename, n))
+ n += 1
+ end until !@@cleanlist.include?(tmpname) and yield(tmpname)
rescue
+ p $!
failure += 1
retry if failure < MAX_TRY
@@ -49,13 +42,63 @@ class Tempfile < DelegateClass(File)
end

- @data = [tmpname]
- @clean_proc = Tempfile.callback(@data)
+ tmpname
+ end
+
+ def self.callback(path, clear) # :nodoc:
+ @@cleanlist << path
+ data = [path]
+ pid = $$
+ return Proc.new {
+ if pid == $$
+ path, tmpfile = *data
+
+ print "removing ", path, "..." if $DEBUG
+
+ tmpfile.close if tmpfile
+
+ # keep this order for thread safeness
+ if File.exist?(path)
+ clear.call(path)
+ end
+ @@cleanlist.delete(path)
+
+ print "done\n" if $DEBUG
+ end
+ }, data
+ end
+
+ def self.unregister(path)
+ @@cleanlist.delete(path)
+ end
+end
+
+# A class for managing temporary files. This library is written to be
+# thread safe.
+class Tempfile < DelegateClass(File)
+ include AutoRemoval
+
+ # Creates a temporary file of mode 0600 in the temporary directory
+ # whose name is basename.pid.n and opens with mode "w+". A Tempfile
+ # object works just like a File object.
+ #
+ # If tmpdir is omitted, the temporary directory is determined by
+ # Dir::tmpdir provided by 'tmpdir.rb'.
+ # When $SAFE > 0 and the given tmpdir is tainted, it uses
+ # /tmp. (Note that ENV values are tainted by default)
+ def initialize(*args)
+ lock = nil
+ tmpname = createtmp(*args) do |tmpname|
+ lock = tmpname + '.lock'
+ unless File.exist?(lock) or File.exist?(tmpname)
+ Dir.mkdir(lock)
+ end
+ end
+
+ @clean_proc, @data = AutoRemoval.callback(tmpname, File.method(:unlink))
ObjectSpace.define_finalizer(self, @clean_proc)

@tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
@tmpname = tmpname
- @@cleanlist << @tmpname
@data[1] = @tmpfile
- @data[2] = @@cleanlist

super(@tmpfile)
@@ -67,9 +110,4 @@ class Tempfile < DelegateClass(File)
end

- def make_tmpname(basename, n)
- sprintf('%s%d.%d', basename, $$, n)
- end
- private :make_tmpname
-
# Opens or reopens the file with mode "r+".
def open
@@ -87,5 +125,5 @@ class Tempfile < DelegateClass(File)
protected :_close

- #Closes the file. If the optional flag is true, unlinks the file
+ # Closes the file. If the optional flag is true, unlinks the file
# after closing.
#
@@ -116,5 +154,5 @@ class Tempfile < DelegateClass(File)
begin
File.unlink(@tmpname) if File.exist?(@tmpname)
- @@cleanlist.delete(@tmpname)
+ AutoRemoval.unregister(@tmpname)
@data = @tmpname = nil
ObjectSpace.undefine_finalizer(self)
@@ -143,23 +181,4 @@ class Tempfile < DelegateClass(File)

class << self
- def callback(data) # :nodoc:
- pid = $$
- Proc.new {
- if pid == $$
- path, tmpfile, cleanlist = *data
-
- print "removing ", path, "..." if $DEBUG
-
- tmpfile.close if tmpfile
-
- # keep this order for thread safeness
- File.unlink(path) if File.exist?(path)
- cleanlist.delete(path) if cleanlist
-
- print "done\n" if $DEBUG
- end
- }
- end
-
# If no block is given, this is a synonym for new().
#
@@ -185,4 +204,33 @@ class Tempfile < DelegateClass(File)
end

+require 'pathname'
+class Tempdir < Pathname
+ include AutoRemoval
+
+ def initialize(*args)
+ require 'fileutils'
+
+ tmpname = createtmp(*args) do |tmpname|
+ unless File.exist?(tmpname)
+ Dir.mkdir(tmpname, 0700)
+ end
+ end
+
+ super(tmpname)
+ @clean_proc, = AutoRemoval.callback(tmpname, FileUtils.method(:rm_rf))
+ ObjectSpace.define_finalizer(self, @clean_proc)
+ end
+
+ def open(basename, *modes, &block)
+ File.open(self+basename, *modes, &block)
+ end
+
+ def clear
+ FileUtils.rm_rf(@tmpname)
+ @clean_proc.call
+ ObjectSpace.undefine_finalizer(self)
+ end
+end
+
if __FILE__ == $0
# $DEBUG = true
@@ -193,3 +241,6 @@ if __FILE__ == $0
p f.gets # => "foo\n"
f.close!
+ d = Tempdir.new("hoge")
+ system("ls", "-dl", d.to_s)
+ p d
end


--
Nobu Nakada


 
Reply With Quote
 
 
 
 
Wybo Dekker
Guest
Posts: n/a
 
      04-04-2005
On Sat, 2 Apr 2005 http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:

> Hi,
>
> At Sat, 2 Apr 2005 18:26:51 +0900,
> Wybo Dekker wrote in [ruby-talk:136465]:
> > I would like to create a temporary directory that disappears
> > after exit (analogous to Tempfile). But ruby doesn't seem to have a
> > Tempdir class?

>
> Once I had proposed it at [ruby-dev:21336], and this is the
> patch for latest version.


Thanks, that worked! But one question still:

I took the tempfile.rb from the cvs, patched it, then moved it into the
1.8.2 library. The original tempfile there had "lambda {", where the new
file has "Proc.new {". No problems to be expected?

--
Wybo


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
anonymous array of strings // ("taking address of temporary"- how long is temporary valid?) anon.asdf@gmail.com C++ 7 02-12-2008 10:58 AM
System.IO.Directory.GetDirectories() and System.IO.Directory.GetFiles() are not returning the specified directory Nathan Sokalski ASP .Net 2 09-06-2007 03:58 PM
Directory and files names in temporary asp.net directory =?Utf-8?B?QmFzIEhlbmRyaWtz?= ASP .Net 5 01-31-2005 01:56 PM
RE: Could not copy temporary files to the output directory Charlie Nilsson [MSFT] ASP .Net 0 08-29-2003 11:22 PM



Advertisments