<?xml version="1.0" encoding="EUC-JP" ?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>ruby-src:lib/tempfile.rb</title> <meta http-equiv="Content-type" content="text/html; charset=EUC-JP" /> <link href="default.css" type="text/css" rel="stylesheet" /> <link href="refm469.html" rel="next" /> <link href="refm467.html" rel="prev" /> <link href="index.html" rel="start" /> </head> <body> <div class="navigator"><span class="navigator">[<a href="index.html">MAIN</a>][<a href="refm482.html">INDEX</a>][<a href="refm483.html">KEYWORD</a>][<a href="refm594.html">METHOD</a>(<a href="refm633.html">NC</a>)] [<a href="index.html">TOP</a>][<a href="index.html">UP</a>][<a href="refm467.html"><-PREV</a>][<a href="refm469.html">NEXT-></a>]</span></div> <hr /> <h1>ruby-src:lib/tempfile.rb</h1> #<br /> # tempfile - manipulates temporary files<br /> #<br /> # $Id: tempfile.rb,v 1.24 2004/05/07 08:44:22 matz Exp $<br /> #<br /> <br /> require 'delegate'<br /> require 'tmpdir'<br /> <br /> # A class for managing temporary files. This library is written to be<br /> # thread safe.<br /> class Tempfile < DelegateClass(File)<br /> MAX_TRY = 10<br /> @@cleanlist = []<br /> <br /> # Creates a temporary file of mode 0600 in the temporary directory<br /> # whose name is basename.pid.n and opens with mode "w+". A Tempfile<br /> # object works just like a File object.<br /> #<br /> # If tmpdir is omitted, the temporary directory is determined by<br /> # Dir::tmpdir provided by 'tmpdir.rb'.<br /> # When $SAFE > 0 and the given tmpdir is tainted, it uses<br /> # /tmp. (Note that ENV values are tainted by default)<br /> def initialize(basename, tmpdir=Dir::tmpdir)<br /> if $SAFE > 0 and tmpdir.tainted?<br /> tmpdir = '/tmp'<br /> end<br /> <br /> lock = nil<br /> n = failure = 0<br /> <br /> begin<br /> Thread.critical = true<br /> <br /> begin<br /> tmpname = sprintf('%s/%s%d.%d', tmpdir, basename, $$, n)<br /> lock = tmpname + '.lock'<br /> n += 1<br /> end while @@cleanlist.include?(tmpname) or<br /> File.exist?(lock) or File.exist?(tmpname)<br /> <br /> Dir.mkdir(lock)<br /> rescue<br /> failure += 1<br /> retry if failure < MAX_TRY<br /> raise "cannot generate tempfile `%s'" % tmpname<br /> ensure<br /> Thread.critical = false<br /> end<br /> <br /> @data = [tmpname]<br /> @clean_proc = Tempfile.callback(@data)<br /> ObjectSpace.define_finalizer(self, @clean_proc)<br /> <br /> @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)<br /> @tmpname = tmpname<br /> @@cleanlist << @tmpname<br /> @data[1] = @tmpfile<br /> @data[2] = @@cleanlist<br /> <br /> super(@tmpfile)<br /> <br /> # Now we have all the File/IO methods defined, you must not<br /> # carelessly put bare puts(), etc. after this.<br /> <br /> Dir.rmdir(lock)<br /> end<br /> <br /> # Opens or reopens the file with mode "r+".<br /> def open<br /> @tmpfile.close if @tmpfile<br /> @tmpfile = File.open(@tmpname, 'r+')<br /> @data[1] = @tmpfile<br /> __setobj__(@tmpfile)<br /> end<br /> <br /> def _close # :nodoc:<br /> @tmpfile.close if @tmpfile<br /> @tmpfile = nil<br /> @data[1] = nil if @data<br /> end<br /> protected :_close<br /> <br /> #Closes the file. If the optional flag is true, unlinks the file<br /> # after closing.<br /> #<br /> # If you don't explicitly unlink the temporary file, the removal<br /> # will be delayed until the object is finalized.<br /> def close(unlink_now=false)<br /> if unlink_now<br /> close!<br /> else<br /> _close<br /> end<br /> end<br /> <br /> # Closes and unlinks the file.<br /> def close!<br /> _close<br /> @clean_proc.call<br /> ObjectSpace.undefine_finalizer(self)<br /> @data = @tmpname = nil<br /> end<br /> <br /> # Unlinks the file. On UNIX-like systems, it is often a good idea<br /> # to unlink a temporary file immediately after creating and opening<br /> # it, because it leaves other programs zero chance to access the<br /> # file.<br /> def unlink<br /> # keep this order for thread safeness<br /> begin<br /> File.unlink(@tmpname) if File.exist?(@tmpname)<br /> @@cleanlist.delete(@tmpname)<br /> @tmpname = nil<br /> rescue Errno::EACCESS<br /> # may not be able to unlink on Windows; just ignore<br /> end<br /> end<br /> alias delete unlink<br /> <br /> # Returns the full path name of the temporary file.<br /> def path<br /> @tmpname<br /> end<br /> <br /> # Returns the size of the temporary file. As a side effect, the IO<br /> # buffer is flushed before determining the size.<br /> def size<br /> if @tmpfile<br /> @tmpfile.flush<br /> @tmpfile.stat.size<br /> else<br /> 0<br /> end<br /> end<br /> alias length size<br /> <br /> class << self<br /> def callback(data) # :nodoc:<br /> pid = $$<br /> lambda{<br /> if pid == $$ <br /> path, tmpfile, cleanlist = *data<br /> <br /> print "removing ", path, "..." if $DEBUG<br /> <br /> tmpfile.close if tmpfile<br /> <br /> # keep this order for thread safeness<br /> File.unlink(path) if File.exist?(path)<br /> cleanlist.delete(path) if cleanlist<br /> <br /> print "done\n" if $DEBUG<br /> end<br /> }<br /> end<br /> <br /> # If no block is given, this is a synonym for new().<br /> #<br /> # If a block is given, it will be passed tempfile as an argument,<br /> # and the tempfile will automatically be closed when the block<br /> # terminates. In this case, open() returns nil.<br /> def open(*args)<br /> tempfile = new(*args)<br /> <br /> if block_given?<br /> begin<br /> yield(tempfile)<br /> ensure<br /> tempfile.close<br /> end<br /> <br /> nil<br /> else<br /> tempfile<br /> end<br /> end<br /> end<br /> end<br /> <br /> if __FILE__ == $0<br /> # $DEBUG = true<br /> f = Tempfile.new("foo")<br /> f.print("foo\n")<br /> f.close<br /> f.open<br /> p f.gets # => "foo\n"<br /> f.close!<br /> end<br /> <hr /> <div class="navigator"><span class="navigator">[<a href="index.html">MAIN</a>][<a href="refm482.html">INDEX</a>][<a href="refm483.html">KEYWORD</a>][<a href="refm594.html">METHOD</a>(<a href="refm633.html">NC</a>)] [<a href="index.html">TOP</a>][<a href="index.html">UP</a>][<a href="refm467.html"><-PREV</a>][<a href="refm469.html">NEXT-></a>]</span></div> </body> </html>