diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-09-08 13:38:01 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2009-09-08 13:38:01 +0000 |
commit | 032a314c5025d2d87e5ea11c58162e698fff0168 (patch) | |
tree | 7afb2017f336e7db02e11d9205de911d9cfcf40b | |
parent | e6dd856d73d084371c0b916cdfabf5775c1d0375 (diff) | |
download | ruby-032a314c5025d2d87e5ea11c58162e698fff0168.tar.gz |
* lib/tempfile.rb, lib/tmpdir.rb (Tmpname): extracted new module.
[ruby-dev:39197]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@24795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 5 | ||||
-rwxr-xr-x | lib/tempfile.rb | 82 | ||||
-rw-r--r-- | lib/tmpdir.rb | 89 |
3 files changed, 84 insertions, 92 deletions
@@ -1,3 +1,8 @@ +Tue Sep 8 22:37:59 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> + + * lib/tempfile.rb, lib/tmpdir.rb (Tmpname): extracted new module. + [ruby-dev:39197] + Tue Sep 8 22:18:11 2009 Nobuyoshi Nakada <nobu@ruby-lang.org> * st.c (st_init_*table_with_size): use st_index_t. diff --git a/lib/tempfile.rb b/lib/tempfile.rb index 46164e8b99..4ebeea28a1 100755 --- a/lib/tempfile.rb +++ b/lib/tempfile.rb @@ -80,8 +80,7 @@ require 'thread' # mutex. class Tempfile < DelegateClass(File) MAX_TRY = 10 # :nodoc: - @@cleanlist = [] - @@lock = Mutex.new + include Dir::Tmpname # call-seq: # new(basename, [tmpdir = Dir.tmpdir], [options]) @@ -128,70 +127,24 @@ class Tempfile < DelegateClass(File) # If Tempfile.new cannot find a unique filename within a limited # number of tries, then it will raise an exception. def initialize(basename, *rest) - # I wish keyword argument settled soon. - if opts = Hash.try_convert(rest[-1]) - rest.pop - end - tmpdir = rest[0] || Dir::tmpdir - if $SAFE > 0 and tmpdir.tainted? - tmpdir = '/tmp' - end + @data = [] + @clean_proc = self.class.callback(@data) + ObjectSpace.define_finalizer(self, @clean_proc) - lock = tmpname = nil - n = failure = 0 - @@lock.synchronize { + create(basename, *rest) do |tmpname, n, opts| + lock = tmpname + '.lock' + self.class.mkdir(lock) begin - 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) - rescue - failure += 1 - retry if failure < MAX_TRY - raise "cannot generate tempfile `#{tmpname}'" + @data[1] = @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600, *opts) + @data[0] = @tmpname = tmpname + ensure + self.class.rmdir(lock) end - } - - @data = [tmpname] - @clean_proc = Tempfile.callback(@data) - ObjectSpace.define_finalizer(self, @clean_proc) - - if opts.nil? - opts = [] - else - opts = [opts] end - @tmpfile = File.open(tmpname, File::RDWR|File::CREAT|File::EXCL, 0600, *opts) - @tmpname = tmpname - @@cleanlist << @tmpname - @data[1] = @tmpfile - @data[2] = @@cleanlist super(@tmpfile) - - # Now we have all the File/IO methods defined, you must not - # carelessly put bare puts(), etc. after this. - - Dir.rmdir(lock) end - def make_tmpname(basename, n) - case basename - when Array - prefix, suffix = *basename - else - prefix, suffix = basename, '' - end - - t = Time.now.strftime("%Y%m%d") - th = Thread.current.object_id - path = "#{prefix}#{t}-#{$$}-#{th.to_s(36)}-#{rand(0x100000000).to_s(36)}-#{n}#{suffix}" - end - private :make_tmpname - # Opens or reopens the file with mode "r+". def open @tmpfile.close if @tmpfile @@ -269,8 +222,7 @@ class Tempfile < DelegateClass(File) if File.exist?(@tmpname) File.unlink(@tmpname) end - @@cleanlist.delete(@tmpname) - # remove tmpname and cleanlist from callback + # remove tmpname from callback @data[0] = @data[2] = nil @data = @tmpname = nil rescue Errno::EACCES @@ -302,7 +254,7 @@ class Tempfile < DelegateClass(File) pid = $$ Proc.new { if pid == $$ - path, tmpfile, cleanlist = *data + path, tmpfile = *data STDERR.print "removing ", path, "..." if $DEBUG @@ -311,7 +263,6 @@ class Tempfile < DelegateClass(File) # keep this order for thread safeness if path File.unlink(path) if File.exist?(path) - cleanlist.delete(path) if cleanlist end STDERR.print "done\n" if $DEBUG @@ -354,6 +305,13 @@ class Tempfile < DelegateClass(File) tempfile end end + + def mkdir(*args) + Dir.mkdir(*args) + end + def rmdir(*args) + Dir.rmdir(*args) + end end end diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb index 0d247bdd54..0aa9cf5e3b 100644 --- a/lib/tmpdir.rb +++ b/lib/tmpdir.rb @@ -10,8 +10,12 @@ class Dir @@systmpdir = '/tmp' - begin - require 'Win32API' + if /mswin|mingw|cygwin/ =~ RUBY_PLATFORM and + begin + require 'Win32API' + true + rescue LoadError + end CSIDL_LOCAL_APPDATA = 0x001c max_pathlen = 260 windir = "\0"*(max_pathlen+1) @@ -30,7 +34,6 @@ class Dir windir.force_encoding(Dir.pwd.encoding) temp = File.expand_path('temp', windir.untaint) @@systmpdir = temp if File.directory?(temp) and File.writable?(temp) - rescue LoadError end ## @@ -95,41 +98,67 @@ class Dir # FileUtils.remove_entry_secure dir # end # - def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil) - case prefix_suffix - when nil - prefix = "d" - suffix = "" - when String - prefix = prefix_suffix - suffix = "" - when Array - prefix = prefix_suffix[0] - suffix = prefix_suffix[1] + def Dir.mktmpdir(prefix_suffix=nil, *rest) + path = Tmpname.create(prefix_suffix || "d", *rest) {|n| mkdir(n, 0700)} + if block_given? + begin + yield path + ensure + FileUtils.remove_entry_secure path + end else - raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}" + path end - tmpdir ||= Dir.tmpdir - t = Time.now.strftime("%Y%m%d") - n = nil - begin - path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}" + end + + module Tmpname + module_function + + def tmpdir + Dir.tmpdir + end + + def make_tmpname(prefix_suffix, n) + case prefix_suffix + when String + prefix = prefix_suffix + suffix = "" + when Array + prefix = prefix_suffix[0] + suffix = prefix_suffix[1] + else + raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}" + end + t = Time.now.strftime("%Y%m%d") + path = "#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}" path << "-#{n}" if n path << suffix - Dir.mkdir(path, 0700) - rescue Errno::EEXIST - n ||= 0 - n += 1 - retry end - if block_given? + def create(basename, *rest) + if opts = Hash.try_convert(rest[-1]) + opts = opts.dup if rest.pop.equal?(opts) + max_try = opts.delete(:max_try) + opts = [opts] + else + opts = [] + end + tmpdir, = *rest + if $SAFE > 0 and tmpdir.tainted? + tmpdir = '/tmp' + else + tmpdir ||= tmpdir() + end + n = nil begin - yield path - ensure - FileUtils.remove_entry_secure path + path = File.expand_path(make_tmpname(basename, n), tmpdir) + yield(path, n, opts) + rescue Errno::EEXIST + n ||= 0 + n += 1 + retry if !max_try or n < max_try + raise "cannot generate temporary name using `#{basename}' under `#{tmpdir}'" end - else path end end |