clutil 2014.304.0 → 2014.304.1
Sign up to get free protection for your applications and to get access to all the features.
- data/cl/util/clqsend.rb +54 -0
- data/cl/util/console.rb +27 -0
- data/cl/util/decide.rb +69 -0
- data/cl/util/dirsize.rb +112 -0
- data/cl/util/file.rb +280 -0
- data/cl/util/install.rb +84 -0
- data/cl/util/install.util.rb +34 -0
- data/cl/util/net.rb +35 -0
- data/cl/util/progress.rb +71 -0
- data/cl/util/smtp.rb +138 -0
- data/cl/util/string.rb +38 -0
- data/cl/util/test.rb +56 -0
- data/cl/util/time.rb +35 -0
- data/cl/util/win.rb +318 -0
- metadata +18 -4
data/cl/util/clqsend.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'cl/util/smtp'
|
2
|
+
|
3
|
+
def getSwitch(switch)
|
4
|
+
i = ARGV.index(switch)
|
5
|
+
if i != nil
|
6
|
+
ARGV[i + 1]
|
7
|
+
else
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def showhelp
|
13
|
+
puts '-h Help'
|
14
|
+
puts '-t To'
|
15
|
+
puts '-f From'
|
16
|
+
puts '-bf file name of body'
|
17
|
+
puts '-s Subject'
|
18
|
+
puts '-i SMTP ip address or server name'
|
19
|
+
end
|
20
|
+
|
21
|
+
if ARGV.include?('-h')
|
22
|
+
showhelp
|
23
|
+
else
|
24
|
+
to = getSwitch('-t')
|
25
|
+
subj = getSwitch('-s')
|
26
|
+
from = getSwitch('-f')
|
27
|
+
bodyfn = getSwitch('-bf')
|
28
|
+
smtpsrv = getSwitch('-i')
|
29
|
+
params = {
|
30
|
+
:from.to_s => from,
|
31
|
+
:to.to_s => to,
|
32
|
+
:subj.to_s => subj,
|
33
|
+
:bodyfn.to_s => bodyfn,
|
34
|
+
:smtpsrv.to_s => smtpsrv
|
35
|
+
}
|
36
|
+
anymissing = false
|
37
|
+
params.each do |key, value|
|
38
|
+
if value == nil
|
39
|
+
puts 'missing param <' + key + '>'
|
40
|
+
anymissing = true
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
body = File.readlines(bodyfn).join
|
45
|
+
|
46
|
+
if !anymissing
|
47
|
+
puts "sending To:#{to} From:#{from} Subj:#{subj}"
|
48
|
+
puts body
|
49
|
+
sendmail(to, from, subj, body, smtpsrv)
|
50
|
+
else
|
51
|
+
puts
|
52
|
+
showhelp
|
53
|
+
end
|
54
|
+
end
|
data/cl/util/console.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
def ifSwitch(switch)
|
2
|
+
ARGV.index(switch) != nil
|
3
|
+
end
|
4
|
+
|
5
|
+
alias :if_switch :ifSwitch
|
6
|
+
|
7
|
+
def getSwitch(switch)
|
8
|
+
value = nil
|
9
|
+
i = ARGV.index(switch)
|
10
|
+
value = ARGV[i + 1] if i != nil
|
11
|
+
end
|
12
|
+
|
13
|
+
alias :get_switch :getSwitch
|
14
|
+
|
15
|
+
def yn_prompt(text, &blk)
|
16
|
+
custom_prompt(text + '? (Y/[N]):', /y/i, @yesToAll, &blk)
|
17
|
+
end
|
18
|
+
|
19
|
+
def custom_prompt(text, execReply=/y/i, autoYield=false)
|
20
|
+
if !autoYield
|
21
|
+
print text
|
22
|
+
reply = $stdin.gets.chomp
|
23
|
+
else
|
24
|
+
puts text
|
25
|
+
end
|
26
|
+
yield reply if reply =~ execReply || autoYield
|
27
|
+
end
|
data/cl/util/decide.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
class Integer
|
2
|
+
def odd?
|
3
|
+
self.divmod(2)[1] != 0
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
def decide(items)
|
8
|
+
round = 1
|
9
|
+
while items.length > 1
|
10
|
+
items.sort! { rand(3) - 1 }
|
11
|
+
|
12
|
+
pairs = []
|
13
|
+
gate = 0
|
14
|
+
items.each { |item|
|
15
|
+
pairs << [item] if gate == 0
|
16
|
+
pairs[-1] << item if gate == 1
|
17
|
+
gate = gate ^ 1
|
18
|
+
}
|
19
|
+
|
20
|
+
puts "=" * 20
|
21
|
+
puts "Round #{round} :: #{pairs.length} pairs".center(20)
|
22
|
+
puts "=" * 20
|
23
|
+
|
24
|
+
pairs.each do |pair|
|
25
|
+
begin
|
26
|
+
puts "1) #{pair[0]}"
|
27
|
+
puts "2) #{pair[1]}"
|
28
|
+
print "keep: "
|
29
|
+
keeper = gets.chomp
|
30
|
+
end while keeper !~ /[12]/
|
31
|
+
delete = (keeper.to_i - 1) ^ 1
|
32
|
+
items.delete(pair[delete])
|
33
|
+
end
|
34
|
+
round += 1
|
35
|
+
end
|
36
|
+
|
37
|
+
puts "Winner is: #{items[0]}"
|
38
|
+
end
|
39
|
+
|
40
|
+
if __FILE__ == $0
|
41
|
+
def do_test
|
42
|
+
puts "Odd number item list test"
|
43
|
+
items = ["a", "b", "c", "d", "e"]
|
44
|
+
decide(items)
|
45
|
+
|
46
|
+
puts "Even number item list test"
|
47
|
+
items = ["a", "b", "c", "d"]
|
48
|
+
decide(items)
|
49
|
+
end
|
50
|
+
|
51
|
+
list_fn = ARGV[0]
|
52
|
+
ARGV.clear
|
53
|
+
|
54
|
+
if list_fn =~ /test/i
|
55
|
+
do_test
|
56
|
+
exit
|
57
|
+
end
|
58
|
+
|
59
|
+
if list_fn.nil? || !File.exists?(list_fn)
|
60
|
+
puts "Usage: #{File.basename(__FILE__)} [list_filename]"
|
61
|
+
exit
|
62
|
+
end
|
63
|
+
|
64
|
+
items = File.readlines(list_fn)
|
65
|
+
items.delete_if { |item| item.chomp.empty? }
|
66
|
+
items.compact!
|
67
|
+
decide(items)
|
68
|
+
end
|
69
|
+
|
data/cl/util/dirsize.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
=begin
|
2
|
+
uses Classes;
|
3
|
+
|
4
|
+
type
|
5
|
+
{ future, make a cache/factory object for TDirSizes, so we don't have to
|
6
|
+
recalc dirs we've already sized }
|
7
|
+
|
8
|
+
TDirSize = class(TObject)
|
9
|
+
private
|
10
|
+
@diskSpace: Int64;
|
11
|
+
@fileCount: integer;
|
12
|
+
@fileSize: Int64;
|
13
|
+
FClusterSize: Int64;
|
14
|
+
FDirectory: string;
|
15
|
+
FParent: TDirSize;
|
16
|
+
|
17
|
+
FChildDirs: TList;
|
18
|
+
public
|
19
|
+
constructor Create;
|
20
|
+
destructor Destroy; override;
|
21
|
+
|
22
|
+
function AvgFileSize(IncludeSubs: boolean): Int64;
|
23
|
+
function DiskSpace(IncludeSubs: boolean): Int64;
|
24
|
+
function FileCount(IncludeSubs: boolean): integer;
|
25
|
+
function FileSize(IncludeSubs: boolean): Int64;
|
26
|
+
procedure GetSize;
|
27
|
+
function UnusedDiskSpace(IncludeSubs: boolean): Int64;
|
28
|
+
|
29
|
+
property ChildDirs: TList read FChildDirs;
|
30
|
+
property ClusterSize: Int64 read FClusterSize write FClusterSize;
|
31
|
+
property Directory: string read FDirectory write FDirectory;
|
32
|
+
property Parent: TDirSize read FParent;
|
33
|
+
end
|
34
|
+
=end
|
35
|
+
|
36
|
+
class DirSize
|
37
|
+
attr_reader :childDirs, :exception
|
38
|
+
attr_accessor :clusterSize, :directory, :parent
|
39
|
+
|
40
|
+
def avgFileSize(includeSubs=false)
|
41
|
+
aFileCount = fileCount(includeSubs)
|
42
|
+
if aFileCount != 0
|
43
|
+
fileSize(includeSubs) / aFileCount
|
44
|
+
else
|
45
|
+
0
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize
|
50
|
+
@childDirs = []
|
51
|
+
@fileSize = 0
|
52
|
+
@diskSpace = 0
|
53
|
+
@fileCount = 0
|
54
|
+
end
|
55
|
+
|
56
|
+
def diskSpace(includeSubs=false)
|
57
|
+
total = 0
|
58
|
+
@childDirs.each do |adir|
|
59
|
+
total += adir.diskSpace(includeSubs)
|
60
|
+
end if includeSubs
|
61
|
+
total + @diskSpace
|
62
|
+
end
|
63
|
+
|
64
|
+
def fileCount(includeSubs=false)
|
65
|
+
result = @fileCount
|
66
|
+
@childDirs.each do |adir|
|
67
|
+
result += adir.fileCount(includeSubs)
|
68
|
+
end if includeSubs
|
69
|
+
result
|
70
|
+
end
|
71
|
+
|
72
|
+
def fileSize(includeSubs=false)
|
73
|
+
total = 0
|
74
|
+
@childDirs.each do |adir|
|
75
|
+
total += adir.fileSize(includeSubs)
|
76
|
+
end if includeSubs
|
77
|
+
total + @fileSize
|
78
|
+
end
|
79
|
+
|
80
|
+
def getSize(&block)
|
81
|
+
@fileSize = 0
|
82
|
+
@diskSpace = 0
|
83
|
+
@fileCount = 0
|
84
|
+
begin
|
85
|
+
Dir.foreach(@directory) do |entry|
|
86
|
+
if (entry != '.') && (entry != '..')
|
87
|
+
entry = File.join(@directory, entry)
|
88
|
+
if (File.directory?(entry))
|
89
|
+
childDirSize = DirSize.new
|
90
|
+
childDirSize.parent = self
|
91
|
+
childDirSize.directory = entry
|
92
|
+
childDirSize.clusterSize = @clusterSize
|
93
|
+
childDirSize.getSize(&block)
|
94
|
+
@childDirs << childDirSize
|
95
|
+
else
|
96
|
+
if !block_given? || yield(entry)
|
97
|
+
@fileCount += 1
|
98
|
+
@fileSize += File.size(entry)
|
99
|
+
@diskSpace += ((@fileSize / @clusterSize) * @clusterSize) + @clusterSize
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
rescue Exception => e
|
105
|
+
@exception = e
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def unusedDiskSpace(includeSubs=false)
|
110
|
+
diskSpace(includeSubs) - fileSize(includeSubs)
|
111
|
+
end
|
112
|
+
end
|
data/cl/util/file.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
=begin
|
2
|
+
code in copyTree includes code from rubycookbook.org under the following license:
|
3
|
+
--------------------------------------------------------------------------------
|
4
|
+
Copyright (c) Phil Tomson, Brian Takita
|
5
|
+
|
6
|
+
All rights reserved.
|
7
|
+
|
8
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
9
|
+
this software and associated documentation files (the "Software"), to deal in
|
10
|
+
the Software without restriction, including without limitation the rights to
|
11
|
+
use, copy, modify, merge, publish, distribute, and/or sell copies of the
|
12
|
+
Software, and to permit persons to whom the Software is furnished to do so,
|
13
|
+
provided that the above copyright notice(s) and this permission notice appear in
|
14
|
+
all copies of the Software and that both the above copyright notice(s) and this
|
15
|
+
permission notice appear in supporting documentation.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
19
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT
|
20
|
+
SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY
|
21
|
+
CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
|
22
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
|
23
|
+
CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
|
24
|
+
WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
25
|
+
|
26
|
+
Except as contained in this notice, the name of a copyright holder shall not be
|
27
|
+
used in advertising or otherwise to promote the sale, use or other dealings in
|
28
|
+
this Software without prior written authorization of the copyright holder.
|
29
|
+
--------------------------------------------------------------------------------
|
30
|
+
(X11 license)
|
31
|
+
=end
|
32
|
+
|
33
|
+
require 'fileutils'
|
34
|
+
|
35
|
+
class Dir
|
36
|
+
def Dir.empty?(dirname)
|
37
|
+
Dir.entries(dirname).length == 2
|
38
|
+
end
|
39
|
+
|
40
|
+
def Dir.files(dirname)
|
41
|
+
# Dir[dirname + '*'] does the same, except it includes the directory name
|
42
|
+
result = []
|
43
|
+
Dir.entries(dirname).each do |entry|
|
44
|
+
result << entry if File.stat(File.join(dirname, entry)).file?
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class << File
|
51
|
+
def extension(filename)
|
52
|
+
res = filename.scan(/\.[^.]*$/)[0].to_s
|
53
|
+
res.gsub!(/\./, '')
|
54
|
+
res = nil if res.empty?
|
55
|
+
res
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete_all(*files)
|
59
|
+
files.flatten!
|
60
|
+
files.each do |file|
|
61
|
+
# make writable to allow deletion
|
62
|
+
File.chmod(0644, file)
|
63
|
+
File.delete(file)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# returns false if up-to-date check passed and the file was not copied.
|
68
|
+
# returns true if up-to-date check failed and the file was copied.
|
69
|
+
def backup(src, dst, bincompare=false)
|
70
|
+
installed = false
|
71
|
+
if (
|
72
|
+
File.exists?(dst) &&
|
73
|
+
(
|
74
|
+
(File.stat(src).mtime != File.stat(dst).mtime) ||
|
75
|
+
(File.stat(src).size != File.stat(dst).size)
|
76
|
+
)
|
77
|
+
) || !File.exists?(dst) || bincompare
|
78
|
+
FileUtils.install src, dst, :verbose => true
|
79
|
+
installed = true
|
80
|
+
end
|
81
|
+
|
82
|
+
if !File.stat(dst).writable?
|
83
|
+
File.chmod(0644, dst)
|
84
|
+
set_ro = true
|
85
|
+
else
|
86
|
+
set_ro = false
|
87
|
+
end
|
88
|
+
match_mtime(src, dst)
|
89
|
+
File.chmod(0444, dst) if set_ro
|
90
|
+
return installed
|
91
|
+
end
|
92
|
+
|
93
|
+
# XP's utime appears to still have a bug when the file's time is within Daylight Saving Time, but
|
94
|
+
# the current system time is outside Daylight Saving Time. This method will ensure any difference
|
95
|
+
# is compensated for.
|
96
|
+
def match_mtime(src, dst)
|
97
|
+
new_atime = Time.now
|
98
|
+
File.utime(new_atime, File.mtime(src), dst)
|
99
|
+
if File.mtime(src) != File.mtime(dst)
|
100
|
+
new_mtime = File.mtime(src)
|
101
|
+
new_mtime += (File.mtime(src) - File.mtime(dst))
|
102
|
+
File.utime(new_atime, new_mtime, dst)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# human readable size
|
107
|
+
def h_size(filename)
|
108
|
+
size = File.size(filename)
|
109
|
+
return '0B' if size == 0
|
110
|
+
units = %w{B KB MB GB TB}
|
111
|
+
e = (Math.log(size) / Math.log(1024)).floor
|
112
|
+
s = "%.0f" % (size.to_f / 1024**e)
|
113
|
+
s.sub(/\.?0*$/, units[e])
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
class ClUtilFile
|
118
|
+
def ClUtilFile.delTree(rootDirName, pattern='*')
|
119
|
+
if (rootDirName == '/') or (rootDirName.empty?)
|
120
|
+
raise 'Cannot delete root or empty?'
|
121
|
+
end
|
122
|
+
|
123
|
+
if !File.exists?(rootDirName)
|
124
|
+
raise 'rootDirName does not exist'
|
125
|
+
end
|
126
|
+
|
127
|
+
# puts all sub-dirs and filenames in array.
|
128
|
+
# Sub-dirs will be breadth first search.
|
129
|
+
dirsAndFiles = Dir["#{rootDirName}/**/" + pattern]
|
130
|
+
|
131
|
+
# delete all files first
|
132
|
+
dirsAndFiles.each do | dirOrFileName |
|
133
|
+
if FileTest.file?(dirOrFileName)
|
134
|
+
if block_given?
|
135
|
+
File.delete_all(dirOrFileName) if yield dirOrFileName
|
136
|
+
else
|
137
|
+
File.delete_all(dirOrFileName)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# go through array backward to delete dirs in proper order
|
143
|
+
dirsAndFiles.reverse_each do | dirOrFileName |
|
144
|
+
if FileTest.directory?(dirOrFileName)
|
145
|
+
Dir.delete(dirOrFileName) if Dir.empty?(dirOrFileName)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
Dir.delete(rootDirName) if Dir.empty?(rootDirName)
|
150
|
+
end
|
151
|
+
|
152
|
+
=begin
|
153
|
+
1.8 FileUtils has cp_r in it ...
|
154
|
+
|
155
|
+
def ClUtilFile.copyTree(fromDir, toDir, pattern='*')
|
156
|
+
##################################################################
|
157
|
+
# cp_r - recursive copy
|
158
|
+
# usage: cp_r(from,to,file_param,permissions)
|
159
|
+
##################################################################
|
160
|
+
def cp_r(from,to,file_param=".*",permissions = 0644)
|
161
|
+
Dir.mkdir(to) unless FileTest.exists?(to)
|
162
|
+
Dir.chdir(to)
|
163
|
+
|
164
|
+
dirContents = Dir["#{from}/*"]
|
165
|
+
dirContents.each { |entry|
|
166
|
+
file = File.basename(entry)
|
167
|
+
|
168
|
+
if FileTest.directory?(entry)
|
169
|
+
Dir.mkdir(file) unless FileTest.exists?(file)
|
170
|
+
cp_r(entry,file,file_param)
|
171
|
+
Dir.chdir("..") #get back to the dir we were working on
|
172
|
+
else
|
173
|
+
if file =~ file_param
|
174
|
+
begin
|
175
|
+
p = permissions
|
176
|
+
if FileTest.executable?(entry)
|
177
|
+
p = 0744 #make it executable
|
178
|
+
end
|
179
|
+
File.install(entry,file,p)
|
180
|
+
rescue
|
181
|
+
puts "could not copy #{entry} to #{file}"
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
}
|
186
|
+
end #cp_r
|
187
|
+
#example usage
|
188
|
+
#cp_r("/usr/local","my_tmp",".*\.html?")
|
189
|
+
|
190
|
+
end
|
191
|
+
=end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
class Dir
|
196
|
+
# Dir.mktmpdir creates a temporary directory.
|
197
|
+
#
|
198
|
+
# [Copied from Ruby 1.9]
|
199
|
+
#
|
200
|
+
# The directory is created with 0700 permission.
|
201
|
+
#
|
202
|
+
# The prefix and suffix of the name of the directory is specified by
|
203
|
+
# the optional first argument, <i>prefix_suffix</i>.
|
204
|
+
# - If it is not specified or nil, "d" is used as the prefix and no suffix is used.
|
205
|
+
# - If it is a string, it is used as the prefix and no suffix is used.
|
206
|
+
# - If it is an array, first element is used as the prefix and second element is used as a suffix.
|
207
|
+
#
|
208
|
+
# Dir.mktmpdir {|dir| dir is ".../d..." }
|
209
|
+
# Dir.mktmpdir("foo") {|dir| dir is ".../foo..." }
|
210
|
+
# Dir.mktmpdir(["foo", "bar"]) {|dir| dir is ".../foo...bar" }
|
211
|
+
#
|
212
|
+
# The directory is created under Dir.tmpdir or
|
213
|
+
# the optional second argument <i>tmpdir</i> if non-nil value is given.
|
214
|
+
#
|
215
|
+
# Dir.mktmpdir {|dir| dir is "#{Dir.tmpdir}/d..." }
|
216
|
+
# Dir.mktmpdir(nil, "/var/tmp") {|dir| dir is "/var/tmp/d..." }
|
217
|
+
#
|
218
|
+
# If a block is given,
|
219
|
+
# it is yielded with the path of the directory.
|
220
|
+
# The directory and its contents are removed
|
221
|
+
# using FileUtils.remove_entry_secure before Dir.mktmpdir returns.
|
222
|
+
# The value of the block is returned.
|
223
|
+
#
|
224
|
+
# Dir.mktmpdir {|dir|
|
225
|
+
# # use the directory...
|
226
|
+
# open("#{dir}/foo", "w") { ... }
|
227
|
+
# }
|
228
|
+
#
|
229
|
+
# If a block is not given,
|
230
|
+
# The path of the directory is returned.
|
231
|
+
# In this case, Dir.mktmpdir doesn't remove the directory.
|
232
|
+
#
|
233
|
+
# dir = Dir.mktmpdir
|
234
|
+
# begin
|
235
|
+
# # use the directory...
|
236
|
+
# open("#{dir}/foo", "w") { ... }
|
237
|
+
# ensure
|
238
|
+
# # remove the directory.
|
239
|
+
# FileUtils.remove_entry_secure dir
|
240
|
+
# end
|
241
|
+
#
|
242
|
+
def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil)
|
243
|
+
case prefix_suffix
|
244
|
+
when nil
|
245
|
+
prefix = "d"
|
246
|
+
suffix = ""
|
247
|
+
when String
|
248
|
+
prefix = prefix_suffix
|
249
|
+
suffix = ""
|
250
|
+
when Array
|
251
|
+
prefix = prefix_suffix[0]
|
252
|
+
suffix = prefix_suffix[1]
|
253
|
+
else
|
254
|
+
raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}"
|
255
|
+
end
|
256
|
+
tmpdir ||= Dir.tmpdir
|
257
|
+
t = Time.now.strftime("%Y%m%d")
|
258
|
+
n = nil
|
259
|
+
begin
|
260
|
+
path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}"
|
261
|
+
path << "-#{n}" if n
|
262
|
+
path << suffix
|
263
|
+
Dir.mkdir(path, 0700)
|
264
|
+
rescue Errno::EEXIST
|
265
|
+
n ||= 0
|
266
|
+
n += 1
|
267
|
+
retry
|
268
|
+
end
|
269
|
+
|
270
|
+
if block_given?
|
271
|
+
begin
|
272
|
+
yield path
|
273
|
+
ensure
|
274
|
+
FileUtils.remove_entry_secure path
|
275
|
+
end
|
276
|
+
else
|
277
|
+
path
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|