source: extensions/gsdl-video/trunk/installed/cmdline/lib/ruby/1.8/tempfile.rb@ 18425

Last change on this file since 18425 was 18425, checked in by davidb, 15 years ago

Video extension to Greenstone

File size: 4.3 KB
Line 
1#
2# tempfile - manipulates temporary files
3#
4# $Id: tempfile.rb 11708 2007-02-12 23:01:19Z shyouhei $
5#
6
7require 'delegate'
8require 'tmpdir'
9
10# A class for managing temporary files. This library is written to be
11# thread safe.
12class Tempfile < DelegateClass(File)
13 MAX_TRY = 10
14 @@cleanlist = []
15
16 # Creates a temporary file of mode 0600 in the temporary directory
17 # whose name is basename.pid.n and opens with mode "w+". A Tempfile
18 # object works just like a File object.
19 #
20 # If tmpdir is omitted, the temporary directory is determined by
21 # Dir::tmpdir provided by 'tmpdir.rb'.
22 # When $SAFE > 0 and the given tmpdir is tainted, it uses
23 # /tmp. (Note that ENV values are tainted by default)
24 def initialize(basename, tmpdir=Dir::tmpdir)
25 if $SAFE > 0 and tmpdir.tainted?
26 tmpdir = '/tmp'
27 end
28
29 lock = nil
30 n = failure = 0
31
32 begin
33 Thread.critical = true
34
35 begin
36 tmpname = File.join(tmpdir, make_tmpname(basename, n))
37 lock = tmpname + '.lock'
38 n += 1
39 end while @@cleanlist.include?(tmpname) or
40 File.exist?(lock) or File.exist?(tmpname)
41
42 Dir.mkdir(lock)
43 rescue
44 failure += 1
45 retry if failure < MAX_TRY
46 raise "cannot generate tempfile `%s'" % tmpname
47 ensure
48 Thread.critical = false
49 end
50
51 @data = [tmpname]
52 @clean_proc = Tempfile.callback(@data)
53 ObjectSpace.define_finalizer(self, @clean_proc)
54
55 @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600)
56 @tmpname = tmpname
57 @@cleanlist << @tmpname
58 @data[1] = @tmpfile
59 @data[2] = @@cleanlist
60
61 super(@tmpfile)
62
63 # Now we have all the File/IO methods defined, you must not
64 # carelessly put bare puts(), etc. after this.
65
66 Dir.rmdir(lock)
67 end
68
69 def make_tmpname(basename, n)
70 sprintf('%s.%d.%d', basename, $$, n)
71 end
72 private :make_tmpname
73
74 # Opens or reopens the file with mode "r+".
75 def open
76 @tmpfile.close if @tmpfile
77 @tmpfile = File.open(@tmpname, 'r+')
78 @data[1] = @tmpfile
79 __setobj__(@tmpfile)
80 end
81
82 def _close # :nodoc:
83 @tmpfile.close if @tmpfile
84 @data[1] = @tmpfile = nil
85 end
86 protected :_close
87
88 # Closes the file. If the optional flag is true, unlinks the file
89 # after closing.
90 #
91 # If you don't explicitly unlink the temporary file, the removal
92 # will be delayed until the object is finalized.
93 def close(unlink_now=false)
94 if unlink_now
95 close!
96 else
97 _close
98 end
99 end
100
101 # Closes and unlinks the file.
102 def close!
103 _close
104 @clean_proc.call
105 ObjectSpace.undefine_finalizer(self)
106 end
107
108 # Unlinks the file. On UNIX-like systems, it is often a good idea
109 # to unlink a temporary file immediately after creating and opening
110 # it, because it leaves other programs zero chance to access the
111 # file.
112 def unlink
113 # keep this order for thread safeness
114 begin
115 File.unlink(@tmpname) if File.exist?(@tmpname)
116 @@cleanlist.delete(@tmpname)
117 @data = @tmpname = nil
118 ObjectSpace.undefine_finalizer(self)
119 rescue Errno::EACCES
120 # may not be able to unlink on Windows; just ignore
121 end
122 end
123 alias delete unlink
124
125 # Returns the full path name of the temporary file.
126 def path
127 @tmpname
128 end
129
130 # Returns the size of the temporary file. As a side effect, the IO
131 # buffer is flushed before determining the size.
132 def size
133 if @tmpfile
134 @tmpfile.flush
135 @tmpfile.stat.size
136 else
137 0
138 end
139 end
140 alias length size
141
142 class << self
143 def callback(data) # :nodoc:
144 pid = $$
145 lambda{
146 if pid == $$
147 path, tmpfile, cleanlist = *data
148
149 print "removing ", path, "..." if $DEBUG
150
151 tmpfile.close if tmpfile
152
153 # keep this order for thread safeness
154 File.unlink(path) if File.exist?(path)
155 cleanlist.delete(path) if cleanlist
156
157 print "done\n" if $DEBUG
158 end
159 }
160 end
161
162 # If no block is given, this is a synonym for new().
163 #
164 # If a block is given, it will be passed tempfile as an argument,
165 # and the tempfile will automatically be closed when the block
166 # terminates. In this case, open() returns nil.
167 def open(*args)
168 tempfile = new(*args)
169
170 if block_given?
171 begin
172 yield(tempfile)
173 ensure
174 tempfile.close
175 end
176
177 nil
178 else
179 tempfile
180 end
181 end
182 end
183end
184
185if __FILE__ == $0
186# $DEBUG = true
187 f = Tempfile.new("foo")
188 f.print("foo\n")
189 f.close
190 f.open
191 p f.gets # => "foo\n"
192 f.close!
193end
Note: See TracBrowser for help on using the repository browser.