lib/tempfile.rb


DEFINITIONS

This source file includes following functions.


   1  #
   2  # $Id: tempfile.rb,v 1.10 2002/06/04 07:34:19 matz Exp $
   3  #
   4  # The class for temporary files.
   5  #  o creates a temporary file, which name is "basename.pid.n" with mode "w+".
   6  #  o Tempfile objects can be used like IO object.
   7  #  o with tempfile.close(true) created temporary files are removed.
   8  #  o created files are also removed on script termination.
   9  #  o with Tempfile#open, you can reopen the temporary file.
  10  #  o file mode of the temporary files are 0600.
  11  
  12  require 'delegate'
  13  
  14  class Tempfile < SimpleDelegator
  15    Max_try = 10
  16  
  17    def Tempfile.callback(path, data)
  18      pid = $$
  19      lambda{
  20        if pid == $$ 
  21          print "removing ", path, "..." if $DEBUG
  22          data[0].close if data[0]
  23          if File.exist?(path)
  24            File.unlink(path) 
  25          end
  26          if File.exist?(path + '.lock')
  27            Dir.rmdir(path + '.lock')
  28          end
  29          print "done\n" if $DEBUG
  30        end
  31      }
  32    end
  33  
  34    def initialize(basename, tmpdir=ENV['TMPDIR']||ENV['TMP']||ENV['TEMP']||'/tmp')
  35      if $SAFE > 0 and tmpdir.tainted?
  36        tmpdir = '/tmp'
  37      end
  38      n = 0
  39      while true
  40        begin
  41          tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)
  42          lock = tmpname + '.lock'
  43          unless File.exist?(tmpname) or File.exist?(lock)
  44            Dir.mkdir(lock)
  45            break
  46          end
  47        rescue
  48          raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try
  49          #sleep(1)
  50        end
  51        n += 1
  52      end
  53  
  54      @protect = []
  55      @clean_files = Tempfile.callback(tmpname, @protect)
  56      ObjectSpace.define_finalizer(self, @clean_files)
  57  
  58      @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
  59      @protect[0] = @tmpfile
  60      @tmpname = tmpname
  61      super(@tmpfile)
  62      Dir.rmdir(lock)
  63    end
  64  
  65    def Tempfile.open(*args)
  66      Tempfile.new(*args)
  67    end
  68  
  69    def open
  70      @tmpfile.close if @tmpfile
  71      @tmpfile = File.open(@tmpname, 'r+')
  72      @protect[0] = @tmpfile
  73      __setobj__(@tmpfile)
  74    end
  75  
  76    def close(real=false)
  77      @tmpfile.close if @tmpfile
  78      @protect[0] = @tmpfile = nil
  79      if real
  80        @clean_files.call
  81        ObjectSpace.undefine_finalizer(self)
  82      end
  83    end
  84  
  85    def path
  86      @tmpname
  87    end
  88  
  89    def size
  90      if @tmpfile
  91        @tmpfile.flush
  92        @tmpfile.stat.size
  93      else
  94        0
  95      end
  96    end
  97  end
  98  
  99  if __FILE__ == $0
 100  #  $DEBUG = true
 101    f = Tempfile.new("foo")
 102    f.print("foo\n")
 103    f.close
 104    f.open
 105    p f.gets # => "foo\n"
 106    f.close(true)
 107  end