file-temp 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +7 -1
- data/MANIFEST +2 -3
- data/README +28 -23
- data/Rakefile +16 -40
- data/file-temp.gemspec +27 -0
- data/lib/file/temp.rb +211 -0
- data/test/test_file_temp.rb +91 -0
- metadata +46 -15
- data/ext/extconf.rb +0 -13
- data/ext/temp.c +0 -120
- data/test/tc_file_temp.rb +0 -64
data/CHANGES
CHANGED
@@ -1,4 +1,10 @@
|
|
1
|
-
= 1.
|
1
|
+
= 1.1.0 - 21-Oct-2009
|
2
|
+
* Now pure Ruby, using FFI.
|
3
|
+
* Fixed RF Bug #26757 - FILE pointer leak. Thanks go to Eric Wong for the spot.
|
4
|
+
* Renamed and refactored the test file slightly.
|
5
|
+
* Updated the gemspec.
|
6
|
+
|
7
|
+
= 1.0.0 - 12-Apr-2008
|
2
8
|
* Added security via umask().
|
3
9
|
* Version bump to 1.0.0.
|
4
10
|
|
data/MANIFEST
CHANGED
data/README
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
-
|
1
|
+
== Description
|
2
2
|
The file-temp library is an alternate way to handle tempfile generation.
|
3
3
|
|
4
|
-
|
4
|
+
== Requirements
|
5
|
+
ffi 0.5.0 or later
|
6
|
+
|
7
|
+
== Synopsis
|
5
8
|
require 'file/temp'
|
6
9
|
|
7
|
-
fh =
|
10
|
+
fh = File::Temp.new
|
8
11
|
fh.puts "hello"
|
9
12
|
fh.close # => Tempfile automatically deleted
|
10
13
|
|
11
|
-
fh =
|
14
|
+
fh = File::Temp.new(false)
|
12
15
|
fh.puts "world"
|
13
16
|
fh.close # => Tempfile still on your filesystem
|
14
17
|
|
15
|
-
|
16
|
-
|
18
|
+
== Installation
|
19
|
+
=== Rubygems
|
20
|
+
gem install file-temp
|
21
|
+
|
22
|
+
=== Standard Installation
|
17
23
|
rake test (optional)
|
18
24
|
rake install
|
19
25
|
|
20
|
-
==
|
21
|
-
rake test (optional)
|
22
|
-
rake gem_install
|
23
|
-
|
24
|
-
= Motivation
|
26
|
+
== Motivation
|
25
27
|
Ruby's tempfile.rb is overwrought and susceptible to race conditions. This
|
26
28
|
This library uses your system's native tmpfile() or mkstemp() functions
|
27
29
|
instead of trying to handle race conditions manually via pure Ruby.
|
@@ -29,31 +31,34 @@
|
|
29
31
|
This library is also more secure because it restricts file permission via
|
30
32
|
umask() for files created with mkstemp().
|
31
33
|
|
32
|
-
|
34
|
+
== Other libraries
|
33
35
|
I am aware of Cian Synnott's ruby-stemp project. However, I don't like the
|
34
36
|
interface, it's GNU-centric (which causes portability issues), and Cian
|
35
37
|
has disabled all the trackers and mailing lists on the RubyForge project
|
36
38
|
site, as well as online SCM access. So, if he doesn't want feedback, I'm
|
37
39
|
not going to waste time with it.
|
38
40
|
|
39
|
-
|
40
|
-
|
41
|
+
== JRuby
|
42
|
+
As of JRuby 1.3.1 this library will not work with JRuby because it does
|
43
|
+
not support low level systems programming.
|
44
|
+
|
45
|
+
== MS Windows
|
46
|
+
You may need to use the mingw build in order to use this library.
|
41
47
|
|
42
|
-
|
43
|
-
|
48
|
+
== License
|
49
|
+
Artistic 2.0
|
44
50
|
|
45
|
-
|
46
|
-
(C) 2007-
|
51
|
+
== Copyright
|
52
|
+
(C) 2007-2009 Daniel J. Berger
|
47
53
|
All Rights Reserved
|
48
54
|
|
49
|
-
|
50
|
-
This
|
55
|
+
== Warranty
|
56
|
+
This library is provided "as is" and without any express or
|
51
57
|
implied warranties, including, without limitation, the implied
|
52
58
|
warranties of merchantability and fitness for a particular purpose.
|
53
59
|
|
54
|
-
|
60
|
+
== Author
|
55
61
|
Daniel J. Berger
|
56
|
-
djberg96 at gmail dot com
|
57
62
|
|
58
|
-
|
63
|
+
== See also
|
59
64
|
tmpfile(), mkstemp(), tmpnam()
|
data/Rakefile
CHANGED
@@ -1,51 +1,27 @@
|
|
1
1
|
require 'rake'
|
2
|
-
require 'rake/clean'
|
3
2
|
require 'rake/testtask'
|
3
|
+
require 'rbconfig'
|
4
4
|
|
5
|
-
desc
|
6
|
-
task :
|
7
|
-
|
8
|
-
Dir.
|
9
|
-
|
10
|
-
|
11
|
-
obj_file = 'temp.obj'
|
12
|
-
if File.exists?(build_file) || File.exists?(obj_file)
|
13
|
-
sh "#{make} distclean"
|
14
|
-
end
|
15
|
-
File.delete("temp.so.manifest") if File.exists?("temp.so.manifest")
|
16
|
-
end
|
5
|
+
desc 'Install the file-temp library (non-gem)'
|
6
|
+
task :install do
|
7
|
+
dir = File.join(CONFIG['sitelibdir'], 'file')
|
8
|
+
Dir.mkdir(dir) unless File.exists?(dir)
|
9
|
+
file = 'lib/file/temp.rb'
|
10
|
+
FileUtils.cp_r(file, dir, :verbose => true)
|
17
11
|
end
|
18
12
|
|
19
|
-
desc
|
20
|
-
task :
|
21
|
-
|
22
|
-
|
23
|
-
ruby 'extconf.rb'
|
24
|
-
sh "#{make}"
|
25
|
-
build_file = 'temp.' + Config::CONFIG['DLEXT']
|
26
|
-
Dir.mkdir('file') unless File.exists?('file')
|
27
|
-
FileUtils.cp(build_file, 'file')
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
desc "Install the file-temp package"
|
32
|
-
task :install => [:build] do
|
33
|
-
Dir.chdir('ext') do
|
34
|
-
make = RUBY_PLATFORM.match('mswin') ? 'nmake' : 'make'
|
35
|
-
sh "#{make} install"
|
36
|
-
end
|
37
|
-
end
|
13
|
+
desc 'Build the gem'
|
14
|
+
task :gem do
|
15
|
+
spec = eval(IO.read('file-temp.gemspec'))
|
16
|
+
Gem::Builder.new(spec).build
|
38
17
|
|
39
|
-
desc
|
40
|
-
task :install_gem do
|
41
|
-
ruby 'file-temp.gemspec'
|
18
|
+
desc 'Install the file-temp library as a gem'
|
19
|
+
task :install_gem => [:gem] do
|
42
20
|
file = Dir["*.gem"].first
|
43
21
|
sh "gem install #{file}"
|
44
22
|
end
|
45
23
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
t.libs << 'ext'
|
50
|
-
t.test_files = FileList['test/tc_file_temp.rb']
|
24
|
+
Rake::TestTask.new do |t|
|
25
|
+
t.verbose = true
|
26
|
+
t.warning = true
|
51
27
|
end
|
data/file-temp.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.name = 'file-temp'
|
5
|
+
gem.version = '1.1.0'
|
6
|
+
gem.author = 'Daniel J. Berger'
|
7
|
+
gem.email = 'djberg96@gmail.com'
|
8
|
+
gem.homepage = 'http://www.rubyforge.org/projects/shards'
|
9
|
+
gem.summary = 'An alternative way to generate temp files'
|
10
|
+
gem.test_file = 'test/test_file_temp.rb'
|
11
|
+
gem.has_rdoc = true
|
12
|
+
gem.files = Dir['**/*'].delete_if{ |item| item.include?('CVS') }
|
13
|
+
|
14
|
+
gem.extra_rdoc_files = ['CHANGES', 'README', 'MANIFEST']
|
15
|
+
gem.rubyforge_project = 'shards'
|
16
|
+
gem.required_ruby_version = '>= 1.8.6'
|
17
|
+
|
18
|
+
gem.add_dependency('use', '>= 1.3.1')
|
19
|
+
gem.add_dependency('ffi', '>= 0.5.0')
|
20
|
+
gem.add_development_dependency('test-unit', '>= 2.0.3')
|
21
|
+
|
22
|
+
gem.description = <<-EOF
|
23
|
+
The file-temp library provides an alternative approach to generating
|
24
|
+
temporary files. Features included improved security, a superior
|
25
|
+
interface, and better support for MS Windows.
|
26
|
+
EOF
|
27
|
+
end
|
data/lib/file/temp.rb
ADDED
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'rbconfig'
|
2
|
+
require 'ffi'
|
3
|
+
|
4
|
+
class File::Temp < File
|
5
|
+
extend FFI::Library
|
6
|
+
|
7
|
+
# :stopdoc:
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# True if operating system is MS Windows
|
12
|
+
WINDOWS = Config::CONFIG['host_os'] =~ /mswin|win32|dos|cygwin|mingw/i
|
13
|
+
|
14
|
+
if WINDOWS
|
15
|
+
ffi_lib 'msvcrt'
|
16
|
+
|
17
|
+
attach_function '_close', [:int], :int
|
18
|
+
attach_function 'fclose', [:pointer], :int
|
19
|
+
attach_function '_fdopen', [:int, :string], :pointer
|
20
|
+
attach_function '_fileno', [:pointer], :int
|
21
|
+
attach_function '_mktemp', [:string], :string
|
22
|
+
attach_function '_open', [:string, :int, :int], :int
|
23
|
+
attach_function '_open_osfhandle', [:long, :int], :int
|
24
|
+
attach_function 'tmpnam', [:string], :string
|
25
|
+
attach_function '_umask', [:int], :int
|
26
|
+
|
27
|
+
ffi_lib 'kernel32'
|
28
|
+
|
29
|
+
attach_function 'CloseHandle', [:long], :bool
|
30
|
+
attach_function 'CreateFileA', [:string, :ulong, :ulong, :pointer, :ulong, :ulong, :ulong], :long
|
31
|
+
attach_function 'DeleteFileA', [:string], :bool
|
32
|
+
attach_function 'GetTempPathA', [:long, :string], :long
|
33
|
+
attach_function 'GetTempFileNameA', [:string, :string, :uint, :pointer], :uint
|
34
|
+
|
35
|
+
S_IWRITE = 128
|
36
|
+
S_IREAD = 256
|
37
|
+
BINARY = 0x8000
|
38
|
+
SHORT_LIVED = 0x1000
|
39
|
+
GENERIC_READ = 0x80000000
|
40
|
+
GENERIC_WRITE = 0x40000000
|
41
|
+
CREATE_ALWAYS = 2
|
42
|
+
|
43
|
+
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
44
|
+
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
45
|
+
INVALID_HANDLE_VALUE = -1
|
46
|
+
else
|
47
|
+
attach_function 'fileno', [:pointer], :int
|
48
|
+
attach_function 'mkstemp', [:string], :int
|
49
|
+
attach_function 'umask', [:int], :int
|
50
|
+
attach_function 'tmpfile', [], :pointer
|
51
|
+
attach_function 'fclose', [:pointer], :int
|
52
|
+
attach_function 'tmpnam', [:string], :string
|
53
|
+
end
|
54
|
+
|
55
|
+
public
|
56
|
+
|
57
|
+
# :startdoc:
|
58
|
+
|
59
|
+
# The version of the file-temp library.
|
60
|
+
VERSION = '1.1.0'
|
61
|
+
|
62
|
+
if WINDOWS
|
63
|
+
# The temporary directory used on MS Windows.
|
64
|
+
TMPDIR = ENV['TEMP'] || ENV['TMP'] || ENV['USERPROFILE'] || "C:\\Windows\\Temp"
|
65
|
+
else
|
66
|
+
# The temporary directory used on Unix.
|
67
|
+
TMPDIR = ENV['TEMP'] || ENV['TMP'] || ENV['TMPDIR'] || '/tmp'
|
68
|
+
end
|
69
|
+
|
70
|
+
public
|
71
|
+
|
72
|
+
# Creates a new, anonymous, temporary file in your File::Temp::TMPDIR
|
73
|
+
# directory
|
74
|
+
#
|
75
|
+
# If the +delete+ option is set to true (the default) then the temporary file
|
76
|
+
# will be deleted automatically as soon as all references to it are closed.
|
77
|
+
# Otherwise, the file will live on in your File::Temp::TMPDIR path.
|
78
|
+
#
|
79
|
+
# If the +delete+ option is set to false, then the file is not deleted. In
|
80
|
+
# addition, you can supply a string +template+ that the system replaces with
|
81
|
+
# a unique filename. This template should end with 3 to 6 'X' characters.
|
82
|
+
# The default template is 'rb_file_temp_XXXXXX'. In this case the temporary
|
83
|
+
# file lives in the directory where it was created.
|
84
|
+
#
|
85
|
+
# The +template+ argument is ignored if the +delete+ argument is true.
|
86
|
+
#
|
87
|
+
# Example:
|
88
|
+
#
|
89
|
+
# fh = File::Temp.new(true, 'rb_file_temp_XXXXXX') => file
|
90
|
+
# fh.puts 'hello world'
|
91
|
+
# fh.close
|
92
|
+
#
|
93
|
+
def initialize(delete = true, template = 'rb_file_temp_XXXXXX')
|
94
|
+
@fptr = nil
|
95
|
+
|
96
|
+
if delete
|
97
|
+
@fptr = tmpfile()
|
98
|
+
fd = WINDOWS ? _fileno(@fptr) : fileno(@fptr)
|
99
|
+
else
|
100
|
+
begin
|
101
|
+
if WINDOWS
|
102
|
+
template = _mktemp(template)
|
103
|
+
omask = _umask(077)
|
104
|
+
else
|
105
|
+
omask = umask(077)
|
106
|
+
end
|
107
|
+
fd = mkstemp(File.join(TMPDIR, template))
|
108
|
+
raise SystemCallError, 'mkstemp()' if fd < 0
|
109
|
+
ensure
|
110
|
+
WINDOWS ? _umask(omask) : umask(omask)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
super(fd, 'wb+')
|
115
|
+
end
|
116
|
+
|
117
|
+
# The close method was overridden to ensure the internal file pointer we
|
118
|
+
# created in the constructor is closed. It is otherwise identical to the
|
119
|
+
# File#close method.
|
120
|
+
#
|
121
|
+
def close
|
122
|
+
super
|
123
|
+
fclose(@fptr) if @fptr
|
124
|
+
end
|
125
|
+
|
126
|
+
# Generates a unique file name, prefixed with the value of the
|
127
|
+
# File::Temp::TMPDIR constant.
|
128
|
+
#
|
129
|
+
# Note that a file is not actually generated on the filesystem.
|
130
|
+
#
|
131
|
+
def self.temp_name
|
132
|
+
TMPDIR + tmpnam(nil) << '.tmp'
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
|
137
|
+
if WINDOWS
|
138
|
+
# The version of tmpfile() implemented by Microsoft is unacceptable.
|
139
|
+
# It attempts to write to C:\ (root) instead of a temporary directory.
|
140
|
+
# This is not only bad behavior, it won't work on Windows 7 and later
|
141
|
+
# without admin rights due to security restrictions.
|
142
|
+
#
|
143
|
+
# This is a custom implementation based on some code from the Cairo
|
144
|
+
# project.
|
145
|
+
#
|
146
|
+
def tmpfile
|
147
|
+
buf = 1.chr * 1024
|
148
|
+
|
149
|
+
if GetTempPathA(buf.length, buf) == 0
|
150
|
+
raise SystemCallError, 'GetTempPath()'
|
151
|
+
end
|
152
|
+
|
153
|
+
file_name = buf[ /^[^\0]*/ ].chop # remove trailing slash
|
154
|
+
buf = 1.chr * 1024
|
155
|
+
|
156
|
+
if GetTempFileNameA(file_name, 'rb_', 0, buf) == 0
|
157
|
+
raise SystemCallError, 'GetTempFileName()'
|
158
|
+
end
|
159
|
+
|
160
|
+
file_name = buf[ /^[^\0]*/ ]
|
161
|
+
|
162
|
+
handle = CreateFileA(
|
163
|
+
file_name,
|
164
|
+
GENERIC_READ | GENERIC_WRITE,
|
165
|
+
0,
|
166
|
+
nil,
|
167
|
+
CREATE_ALWAYS,
|
168
|
+
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
|
169
|
+
0
|
170
|
+
)
|
171
|
+
|
172
|
+
if handle == INVALID_HANDLE_VALUE
|
173
|
+
DeleteFileA(file_name)
|
174
|
+
raise SystemCallError, 'CreateFile()'
|
175
|
+
end
|
176
|
+
|
177
|
+
fd = _open_osfhandle(handle, 0)
|
178
|
+
|
179
|
+
if fd < 0
|
180
|
+
CloseHandle(handle)
|
181
|
+
raise SystemCallError, 'open_osfhandle()'
|
182
|
+
end
|
183
|
+
|
184
|
+
fp = _fdopen(fd, 'w+b')
|
185
|
+
|
186
|
+
if fp.nil?
|
187
|
+
_close(fd)
|
188
|
+
raise SystemCallError, 'fdopen()'
|
189
|
+
end
|
190
|
+
|
191
|
+
fp
|
192
|
+
end
|
193
|
+
|
194
|
+
# The MS C runtime does not define a mkstemp() function, so we've
|
195
|
+
# created one here.
|
196
|
+
#
|
197
|
+
def mkstemp(template)
|
198
|
+
flags = RDWR | BINARY | CREAT | EXCL | SHORT_LIVED
|
199
|
+
pmode = S_IREAD | S_IWRITE
|
200
|
+
|
201
|
+
fd = _open(template, flags, pmode)
|
202
|
+
|
203
|
+
raise SystemCallError, 'mkstemp()' if fd < 0
|
204
|
+
|
205
|
+
fd
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
# For backwards compatability
|
211
|
+
FileTemp = File::Temp
|
@@ -0,0 +1,91 @@
|
|
1
|
+
######################################################################
|
2
|
+
# test_file_temp.rb
|
3
|
+
#
|
4
|
+
# Test suite for the file-temp library. These tests should be run
|
5
|
+
# via the 'rake test' task.
|
6
|
+
######################################################################
|
7
|
+
require 'rubygems'
|
8
|
+
gem 'test-unit'
|
9
|
+
|
10
|
+
require 'test/unit'
|
11
|
+
require 'file/temp'
|
12
|
+
require 'rbconfig'
|
13
|
+
|
14
|
+
class TC_File_Temp < Test::Unit::TestCase
|
15
|
+
def setup
|
16
|
+
@dir = File::Temp::TMPDIR
|
17
|
+
@template = 'file-temp-test-XXXXX'
|
18
|
+
@fh = nil
|
19
|
+
|
20
|
+
# Because Dir[] doesn't work right with backslashes
|
21
|
+
@dir = @dir.tr("\\", "/") if Config::CONFIG['host_os'] =~ /mswin|win32|dos|cygwin|mingw/i
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_file_temp_version
|
25
|
+
assert_equal('1.1.0', File::Temp::VERSION)
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_file_temp_threaded
|
29
|
+
threads = []
|
30
|
+
assert_nothing_raised{ 100.times{ threads << Thread.new{ File::Temp.new }}}
|
31
|
+
assert_nothing_raised{ threads.join }
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_file_temp_tmpdir
|
35
|
+
assert_not_nil(File::Temp::TMPDIR)
|
36
|
+
assert_kind_of(String, File::Temp::TMPDIR)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_file_temp_auto_delete
|
40
|
+
assert_nothing_raised{ @fh = File::Temp.new }
|
41
|
+
assert_nothing_raised{ @fh.print "hello" }
|
42
|
+
assert_nothing_raised{ @fh.close }
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_file_temp_no_delete
|
46
|
+
assert_nothing_raised{ @fh = File::Temp.new(false) }
|
47
|
+
assert_nothing_raised{ @fh.print "hello" }
|
48
|
+
assert_nothing_raised{ @fh.close }
|
49
|
+
assert_true(Dir["#{@dir}/rb_file_temp*"].length == 1)
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_file_temp_no_delete_with_template
|
53
|
+
assert_nothing_raised{ File::Temp.new(false, 'temp_foo_XXXXXX').close }
|
54
|
+
assert_true(Dir["#{@dir}/temp_foo*"].length >= 1)
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_file_temp_no_delete_with_block
|
58
|
+
assert_nothing_raised{ File::Temp.open(false, 'temp_foo_XXXXXX'){ |fh| fh.puts "hello" } }
|
59
|
+
assert_true(Dir["#{@dir}/temp_foo*"].length >= 1)
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_file_temp_expected_errors
|
63
|
+
assert_raise(TypeError, ArgumentError){ @fh = File::Temp.new(false, 1) }
|
64
|
+
assert_raise(ArgumentError){ @fh = File::Temp.new(true, 'temp_bar_XXXXX', 1) }
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_file_temp_name_basic_functionality
|
68
|
+
assert_respond_to(File::Temp, :temp_name)
|
69
|
+
assert_nothing_raised{ File::Temp.temp_name }
|
70
|
+
assert_kind_of(String, File::Temp.temp_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_file_temp_name
|
74
|
+
assert_equal('.tmp', File.extname(File::Temp.temp_name))
|
75
|
+
end
|
76
|
+
|
77
|
+
def teardown
|
78
|
+
@dir = nil
|
79
|
+
@template = nil
|
80
|
+
@fh.close if @fh && !@fh.closed?
|
81
|
+
@fh = nil
|
82
|
+
|
83
|
+
Dir["temp_*"].each{ |f| File.delete(f) }
|
84
|
+
Dir["rb_file_temp_*"].each{ |f| File.delete(f) }
|
85
|
+
|
86
|
+
Dir.chdir(File::Temp::TMPDIR) do
|
87
|
+
Dir["temp_*"].each{ |f| File.delete(f) }
|
88
|
+
Dir["rb_file_temp_*"].each{ |f| File.delete(f) }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: file-temp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -9,30 +9,61 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date:
|
12
|
+
date: 2009-10-21 00:00:00 -06:00
|
13
13
|
default_executable:
|
14
|
-
dependencies:
|
15
|
-
|
16
|
-
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: use
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.3.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: ffi
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.5.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: test-unit
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.0.3
|
44
|
+
version:
|
45
|
+
description: " The file-temp library provides an alternative approach to generating\n temporary files. Features included improved security, a superior\n interface, and better support for MS Windows.\n"
|
17
46
|
email: djberg96@gmail.com
|
18
47
|
executables: []
|
19
48
|
|
20
|
-
extensions:
|
21
|
-
|
49
|
+
extensions: []
|
50
|
+
|
22
51
|
extra_rdoc_files:
|
23
52
|
- CHANGES
|
24
53
|
- README
|
25
54
|
- MANIFEST
|
26
|
-
- ext/temp.c
|
27
55
|
files:
|
28
|
-
- test/tc_file_temp.rb
|
29
56
|
- CHANGES
|
57
|
+
- file-temp.gemspec
|
58
|
+
- lib/file/temp.rb
|
30
59
|
- MANIFEST
|
31
60
|
- Rakefile
|
32
61
|
- README
|
33
|
-
-
|
62
|
+
- test/test_file_temp.rb
|
34
63
|
has_rdoc: true
|
35
64
|
homepage: http://www.rubyforge.org/projects/shards
|
65
|
+
licenses: []
|
66
|
+
|
36
67
|
post_install_message:
|
37
68
|
rdoc_options: []
|
38
69
|
|
@@ -42,7 +73,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
42
73
|
requirements:
|
43
74
|
- - ">="
|
44
75
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.8.
|
76
|
+
version: 1.8.6
|
46
77
|
version:
|
47
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
79
|
requirements:
|
@@ -53,9 +84,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
84
|
requirements: []
|
54
85
|
|
55
86
|
rubyforge_project: shards
|
56
|
-
rubygems_version: 1.
|
87
|
+
rubygems_version: 1.3.5
|
57
88
|
signing_key:
|
58
|
-
specification_version:
|
59
|
-
summary: An alternative way to generate
|
89
|
+
specification_version: 3
|
90
|
+
summary: An alternative way to generate temp files
|
60
91
|
test_files:
|
61
|
-
- test/
|
92
|
+
- test/test_file_temp.rb
|
data/ext/extconf.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'mkmf'
|
2
|
-
dir_config('tmpfile')
|
3
|
-
|
4
|
-
have_func('tmpfile_s')
|
5
|
-
have_func('_sopen_s')
|
6
|
-
|
7
|
-
unless have_func('tmpfile')
|
8
|
-
raise 'This library is not supported on your platform. Aborting'
|
9
|
-
end
|
10
|
-
|
11
|
-
have_func('mkstemp')
|
12
|
-
|
13
|
-
create_makefile('file/temp')
|
data/ext/temp.c
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
#include <ruby.h>
|
2
|
-
#include <stdio.h>
|
3
|
-
#include <sys/stat.h>
|
4
|
-
|
5
|
-
#ifdef HAVE__SOPEN_S
|
6
|
-
#include <share.h>
|
7
|
-
#endif
|
8
|
-
|
9
|
-
#ifndef HAVE_MKSTEMP
|
10
|
-
#include <fcntl.h>
|
11
|
-
#include <temp.h>
|
12
|
-
#endif
|
13
|
-
|
14
|
-
#ifndef P_tmpdir
|
15
|
-
#define P_tmpdir "/tmp"
|
16
|
-
#endif
|
17
|
-
|
18
|
-
#define VERSION "1.0.0"
|
19
|
-
|
20
|
-
VALUE cFileTemp;
|
21
|
-
|
22
|
-
/* call-seq:
|
23
|
-
* FileTemp.new(delete = true, template = 'rb_file_temp_XXXXXX') => file
|
24
|
-
*
|
25
|
-
* Creates a new, anonymous temporary file in your FileTemp::TMPDIR directory,
|
26
|
-
* or /tmp if that cannot be accessed. If your $TMPDIR environment variable is
|
27
|
-
* set, it will be used instead. If $TMPDIR is not writable by the process, it
|
28
|
-
* will resort back to FileTemp::TMPDIR or /tmp.
|
29
|
-
*
|
30
|
-
* If the +delete+ option is set to true (the default) then the temporary file
|
31
|
-
* will be deleted automatically as soon as all references to it are closed.
|
32
|
-
* Otherwise, the file will live on in your $TMPDIR.
|
33
|
-
*
|
34
|
-
* If the +delete+ option is set to false, then the file is *not* deleted. In
|
35
|
-
* addition, you can supply a string +template+ that the system replaces with
|
36
|
-
* a unique filename. This template should end with 3 to 6 'X' characters.
|
37
|
-
* The default template is 'rb_file_temp_XXXXXX'. In this case the temporary
|
38
|
-
* file lives in the directory where it was created.
|
39
|
-
*
|
40
|
-
* The +template+ argument is ignored if the +delete+ argument is true.
|
41
|
-
*/
|
42
|
-
static VALUE tempfile_init(int argc, VALUE* argv, VALUE self){
|
43
|
-
VALUE v_args[2];
|
44
|
-
VALUE v_delete;
|
45
|
-
VALUE v_template;
|
46
|
-
|
47
|
-
rb_scan_args(argc, argv, "02", &v_delete, &v_template);
|
48
|
-
|
49
|
-
if(NIL_P(v_delete))
|
50
|
-
v_delete = Qtrue;
|
51
|
-
|
52
|
-
if(RTEST(v_delete)){
|
53
|
-
#ifdef HAVE_TMPFILE_S
|
54
|
-
FILE* fptr;
|
55
|
-
|
56
|
-
if(tmpfile_s(&fptr))
|
57
|
-
rb_sys_fail("tmpfile_s()");
|
58
|
-
#else
|
59
|
-
FILE* fptr = tmpfile();
|
60
|
-
if(!fptr)
|
61
|
-
rb_sys_fail("tmpfile()");
|
62
|
-
#endif
|
63
|
-
v_args[0] = INT2FIX(fileno(fptr));
|
64
|
-
}
|
65
|
-
else{
|
66
|
-
int fd, omask;
|
67
|
-
|
68
|
-
if(NIL_P(v_template))
|
69
|
-
v_template = rb_str_new2("rb_file_temp_XXXXXX");
|
70
|
-
|
71
|
-
/* Set the umask to improve security */
|
72
|
-
omask = umask(077);
|
73
|
-
fd = mkstemp(StringValuePtr(v_template));
|
74
|
-
umask(omask);
|
75
|
-
|
76
|
-
if(fd < 0)
|
77
|
-
rb_sys_fail("mkstemp()");
|
78
|
-
|
79
|
-
v_args[0] = INT2FIX(fd);
|
80
|
-
}
|
81
|
-
|
82
|
-
/* This bit of explicitness is necessary for MS Windows */
|
83
|
-
v_args[1] = rb_str_new2("wb+");
|
84
|
-
|
85
|
-
return rb_call_super(2, v_args);
|
86
|
-
}
|
87
|
-
|
88
|
-
/*
|
89
|
-
* Generates a unique file name, prefixed with the value of FileTemp::TMPDIR.
|
90
|
-
* Note that a file is not actually generated on the filesystem.
|
91
|
-
*/
|
92
|
-
static VALUE tempfile_tmpnam(VALUE klass){
|
93
|
-
char buf[L_tmpnam];
|
94
|
-
return rb_str_new2(tmpnam(buf));
|
95
|
-
}
|
96
|
-
|
97
|
-
void Init_temp(){
|
98
|
-
|
99
|
-
/* The FileTemp class creates managed temporary files. Unlike Ruby's
|
100
|
-
* Tempfile class from this standard library, this is a subclass of File.
|
101
|
-
* In addition, the temporary file is automatically deleted when all
|
102
|
-
* references to it are closed (instead of waiting until the Ruby process
|
103
|
-
* is complete).
|
104
|
-
*/
|
105
|
-
cFileTemp = rb_define_class("FileTemp", rb_cFile);
|
106
|
-
|
107
|
-
/* Instance Methods */
|
108
|
-
rb_define_method(cFileTemp, "initialize", tempfile_init, -1);
|
109
|
-
|
110
|
-
/* Singleton Methods */
|
111
|
-
rb_define_singleton_method(cFileTemp, "temp_name", tempfile_tmpnam, 0);
|
112
|
-
|
113
|
-
/* Constants */
|
114
|
-
|
115
|
-
/* ENV['P_tmpdir']: Your system's tmpdir */
|
116
|
-
rb_define_const(cFileTemp, "TMPDIR", rb_str_new2(P_tmpdir));
|
117
|
-
|
118
|
-
/* 0.1.3: The version of this library */
|
119
|
-
rb_define_const(cFileTemp, "VERSION", rb_str_new2(VERSION));
|
120
|
-
}
|
data/test/tc_file_temp.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
######################################################################
|
2
|
-
# tc_file_temp.rb
|
3
|
-
#
|
4
|
-
# Test suite for the file-temp library. These tests should be run
|
5
|
-
# via the 'rake test' task.
|
6
|
-
######################################################################
|
7
|
-
require 'test/unit'
|
8
|
-
require 'file/temp'
|
9
|
-
|
10
|
-
class TC_File_Temp < Test::Unit::TestCase
|
11
|
-
def setup
|
12
|
-
@template = 'file-temp-test-XXXXX'
|
13
|
-
@fh = nil
|
14
|
-
end
|
15
|
-
|
16
|
-
def test_file_temp_version
|
17
|
-
assert_equal('1.0.0', FileTemp::VERSION)
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_file_temp_threaded
|
21
|
-
threads = []
|
22
|
-
assert_nothing_raised{ 100.times{ threads << Thread.new{ FileTemp.new }}}
|
23
|
-
assert_nothing_raised{ threads.join }
|
24
|
-
end
|
25
|
-
|
26
|
-
def test_file_temp_tmpdir
|
27
|
-
assert_not_nil(FileTemp::TMPDIR)
|
28
|
-
assert_kind_of(String, FileTemp::TMPDIR)
|
29
|
-
unless RUBY_PLATFORM.match('mswin')
|
30
|
-
assert_equal(true, ['/tmp', '/var/tmp/'].include?(FileTemp::TMPDIR))
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def test_file_temp_auto_delete
|
35
|
-
assert_nothing_raised{ @fh = FileTemp.new }
|
36
|
-
assert_nothing_raised{ @fh.print "hello" }
|
37
|
-
assert_nothing_raised{ @fh.close }
|
38
|
-
end
|
39
|
-
|
40
|
-
def test_file_temp_no_delete
|
41
|
-
assert_nothing_raised{ @fh = FileTemp.new(false) }
|
42
|
-
assert_equal(true, Dir["rb_file_temp*"].length == 1)
|
43
|
-
assert_nothing_raised{ @fh.print "hello" }
|
44
|
-
assert_nothing_raised{ @fh.close }
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_file_temp_no_delete_with_template
|
48
|
-
assert_nothing_raised{ @fh = FileTemp.new(false, 'temp_foo_XXXXX') }
|
49
|
-
assert_equal(true, Dir["temp_foo*"].length == 1)
|
50
|
-
end
|
51
|
-
|
52
|
-
def test_file_temp_expected_errors
|
53
|
-
assert_raise(TypeError){ @fh = FileTemp.new(false, 1) }
|
54
|
-
assert_raise(ArgumentError){ @fh = FileTemp.new(true, 'temp_bar_XXXXX', 1) }
|
55
|
-
end
|
56
|
-
|
57
|
-
def teardown
|
58
|
-
@template = nil
|
59
|
-
@fh.close if @fh && !@fh.closed?
|
60
|
-
@fh = nil
|
61
|
-
Dir["temp_*"].each{ |f| File.delete(f) }
|
62
|
-
Dir["rb_file_temp_*"].each{ |f| File.delete(f) }
|
63
|
-
end
|
64
|
-
end
|