creating a temporary directory

Discussion in 'Ruby' started by Wybo Dekker, Apr 2, 2005.

  1. Wybo Dekker

    Wybo Dekker Guest

    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
     
    Wybo Dekker, Apr 2, 2005
    #1
    1. Advertising

  2. Wybo Dekker

    Guest

    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
     
    , Apr 2, 2005
    #2
    1. Advertising

  3. Wybo Dekker

    Wybo Dekker Guest

    On Sat, 2 Apr 2005 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
     
    Wybo Dekker, Apr 4, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charlie Nilsson [MSFT]

    RE: Could not copy temporary files to the output directory

    Charlie Nilsson [MSFT], Aug 30, 2003, in forum: ASP .Net
    Replies:
    0
    Views:
    549
    Charlie Nilsson [MSFT]
    Aug 30, 2003
  2. arkam
    Replies:
    1
    Views:
    587
    Jim Cheshire [MSFT]
    Dec 18, 2003
  3. Juleke
    Replies:
    2
    Views:
    2,276
    Juleke
    Apr 12, 2004
  4. =?Utf-8?B?QmFzIEhlbmRyaWtz?=

    Directory and files names in temporary asp.net directory

    =?Utf-8?B?QmFzIEhlbmRyaWtz?=, Jan 28, 2005, in forum: ASP .Net
    Replies:
    5
    Views:
    854
    Juan T. Llibre
    Jan 31, 2005
  5. Replies:
    7
    Views:
    3,265
    James Kanze
    Feb 12, 2008
Loading...

Share This Page