# frozen_string_literal: true## tmpdir - retrieve temporary directory path## $Id$#require_relative'../../fileutils/lib/fileutils'beginrequire'etc.so'rescueLoadError# rescue LoadError for minirubyendclassBundler::Dir<Dir@systmpdir||=defined?(Etc.systmpdir)?Etc.systmpdir:'/tmp'### Returns the operating system's temporary file path.defself.tmpdirtmp=nil['TMPDIR','TMP','TEMP',['system temporary path',@systmpdir],['/tmp']*2,['.']*2].eachdo|name,dir=ENV[name]|nextif!dirdir=File.expand_path(dir)stat=File.stat(dir)rescuenextcasewhen!stat.directory?warn"#{name} is not a directory: #{dir}"when!stat.writable?warn"#{name} is not writable: #{dir}"whenstat.world_writable?&&!stat.sticky?warn"#{name} is world-writable: #{dir}"elsetmp=dirbreakendendraiseArgumentError,"could not find a temporary directory"unlesstmptmpend# Bundler::Dir.mktmpdir creates a temporary directory.## The directory is created with 0700 permission.# Application should not change the permission to make the temporary directory accessible from other users.## 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.## Bundler::Dir.mktmpdir {|dir| dir is ".../d..." }# Bundler::Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }# Bundler::Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }## The directory is created under Bundler::Dir.tmpdir or# the optional second argument <i>tmpdir</i> if non-nil value is given.## Bundler::Dir.mktmpdir {|dir| dir is "#{Bundler::Dir.tmpdir}/d..." }# Bundler::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 Bundler::FileUtils.remove_entry before Bundler::Dir.mktmpdir returns.# The value of the block is returned.## Bundler::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, Bundler::Dir.mktmpdir doesn't remove the directory.## dir = Bundler::Dir.mktmpdir# begin# # use the directory...# open("#{dir}/foo", "w") { ... }# ensure# # remove the directory.# Bundler::FileUtils.remove_entry dir# end#defself.mktmpdir(prefix_suffix=nil,*rest,**options)base=nilpath=Tmpname.create(prefix_suffix||"d",*rest,**options){|p,_,_,d|base=dmkdir(p,0700)}ifblock_given?beginyieldpath.dupensureunlessbasestat=File.stat(File.dirname(path))ifstat.world_writable?and!stat.sticky?raiseArgumentError,"parent directory is world writable but not sticky"endendBundler::FileUtils.remove_entrypathendelsepathendendmoduleTmpname# :nodoc:module_functiondeftmpdirBundler::Dir.tmpdirendUNUSABLE_CHARS=[File::SEPARATOR,File::ALT_SEPARATOR,File::PATH_SEPARATOR,":"].uniq.join("").freezeclass<<(RANDOM=Random.new)MAX=36**6# < 0x100000000defnextrand(MAX).to_s(36)endendprivate_constant:RANDOMdefcreate(basename,tmpdir=nil,max_try: nil,**opts)origdir=tmpdirtmpdir||=tmpdir()n=nilprefix,suffix=basenameprefix=(String.try_convert(prefix)orraiseArgumentError,"unexpected prefix: #{prefix.inspect}")prefix=prefix.delete(UNUSABLE_CHARS)suffix&&=(String.try_convert(suffix)orraiseArgumentError,"unexpected suffix: #{suffix.inspect}")suffix&&=suffix.delete(UNUSABLE_CHARS)begint=Time.now.strftime("%Y%m%d")path="#{prefix}#{t}-#{$$}-#{RANDOM.next}"\"#{n?%[-#{n}]:''}#{suffix||''}"path=File.join(tmpdir,path)yield(path,n,opts,origdir)rescueErrno::EEXISTn||=0n+=1retryif!max_tryorn<max_tryraise"cannot generate temporary name using `#{basename}' under `#{tmpdir}'"endpathendendend