summaryrefslogtreecommitdiff
path: root/lib/tmpdir.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/tmpdir.rb')
-rw-r--r--lib/tmpdir.rb144
1 files changed, 121 insertions, 23 deletions
diff --git a/lib/tmpdir.rb b/lib/tmpdir.rb
index bfc214b6b9..f043ad5006 100644
--- a/lib/tmpdir.rb
+++ b/lib/tmpdir.rb
@@ -1,28 +1,18 @@
#
# tmpdir - retrieve temporary directory path
#
-# $Id: tmpdir.rb,v 1.5.2.1 2005/12/15 15:57:05 matz Exp $
+# $Id$
#
-class Dir
+require 'fileutils'
+begin
+ require 'etc.so'
+rescue LoadError
+end
- @@systmpdir = '/tmp'
+class Dir
- begin
- require 'Win32API'
- max_pathlen = 260
- windir = ' '*(max_pathlen+1)
- begin
- getdir = Win32API.new('kernel32', 'GetSystemWindowsDirectory', 'PL', 'L')
- rescue RuntimeError
- getdir = Win32API.new('kernel32', 'GetWindowsDirectory', 'PL', 'L')
- end
- getdir.call(windir, windir.size)
- windir = File.expand_path(windir.rstrip.untaint)
- temp = File.join(windir, 'temp')
- @@systmpdir = temp if File.directory?(temp) and File.writable?(temp)
- rescue LoadError
- end
+ @@systmpdir ||= defined?(Etc.systmpdir) ? Etc.systmpdir : '/tmp'
##
# Returns the operating system's temporary file path.
@@ -32,14 +22,122 @@ class Dir
if $SAFE > 0
tmp = @@systmpdir
else
- for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'],
- ENV['USERPROFILE'], @@systmpdir, '/tmp']
- if dir and File.directory?(dir) and File.writable?(dir)
+ for dir in [ENV['TMPDIR'], ENV['TMP'], ENV['TEMP'], @@systmpdir, '/tmp']
+ if dir and stat = File.stat(dir) and stat.directory? and stat.writable?
tmp = dir
break
- end
+ end rescue nil
+ end
+ File.expand_path(tmp)
+ end
+ end
+
+ # Dir.mktmpdir creates a temporary directory.
+ #
+ # The directory is created with 0700 permission.
+ #
+ # The prefix and suffix of the name of the directory is specified by
+ # the optional first argument, <i>prefix_suffix</i>.
+ # - If it is not specified or nil, "d" is used as the prefix and no suffix is used.
+ # - If it is a string, it is used as the prefix and no suffix is used.
+ # - If it is an array, first element is used as the prefix and second element is used as a suffix.
+ #
+ # Dir.mktmpdir {|dir| dir is ".../d..." }
+ # Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }
+ # Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }
+ #
+ # The directory is created under Dir.tmpdir or
+ # the optional second argument <i>tmpdir</i> if non-nil value is given.
+ #
+ # Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." }
+ # Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }
+ #
+ # If a block is given,
+ # it is yielded with the path of the directory.
+ # The directory and its contents are removed
+ # using FileUtils.remove_entry_secure before Dir.mktmpdir returns.
+ # The value of the block is returned.
+ #
+ # Dir.mktmpdir {|dir|
+ # # use the directory...
+ # open("#{dir}/foo", "w") { ... }
+ # }
+ #
+ # If a block is not given,
+ # The path of the directory is returned.
+ # In this case, Dir.mktmpdir doesn't remove the directory.
+ #
+ # dir = Dir.mktmpdir
+ # begin
+ # # use the directory...
+ # open("#{dir}/foo", "w") { ... }
+ # ensure
+ # # remove the directory.
+ # FileUtils.remove_entry_secure dir
+ # end
+ #
+ 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
+ path
+ end
+ end
+
+ module Tmpname # :nodoc:
+ 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
+ end
+
+ 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
+ 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
+ path
end
- File.expand_path(tmp)
end
end