file-temp 1.2.1 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +1 -0
- data/CHANGES +10 -0
- data/MANIFEST +5 -2
- data/README +5 -1
- data/Rakefile +4 -7
- data/certs/djberg96_pub.pem +21 -0
- data/file-temp.gemspec +10 -11
- data/lib/file-temp.rb +1 -0
- data/lib/file/{temp_java.rb → java/temp.rb} +4 -3
- data/lib/file/temp.rb +6 -2
- data/lib/file/unix/temp.rb +104 -0
- data/lib/file/windows/temp.rb +219 -0
- data/test/test_file_temp.rb +3 -1
- metadata +51 -19
- metadata.gz.sig +3 -0
- data/lib/file/temp_c.rb +0 -254
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0439e6595202db84a8dea3cfd41b526a0f1adba1
|
4
|
+
data.tar.gz: 135ca4378282ef1eabcef68f2b7b3dbea3193de8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74c529e0f8179a27ebb8428cb1636b5401439b2a546f553960e97c9b305e96cfe327edb196865e9cbaeb99f9bf6ef8c1044cece6442918742b84c5e890243388
|
7
|
+
data.tar.gz: ebba50979466de41024f48e2cfd60dab4439fa3f4cbe9c09fd7914120eba0e53039b936e17633b75a5b06d9052c4e051f3f6c2206d199234613d3e3daddfd8fd
|
checksums.yaml.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
��S{��S��ߖ^H#V�}8�?��'�s��c!�}����rz�x���A(�Z$��Z1t��Ѽ�#�&�Bo������6y�?v��l=`3�����^�s�ti)R7�UB��!���q�����^n/�@�1>��b���v�`�k��FIDtvߣ
|
data.tar.gz.sig
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
|�=�^\��<���ϹnZ�yq��/����ζ �%�����'wX
|
data/CHANGES
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
= 1.3.0 - 9-Apr-2016
|
2
|
+
* This gem is now signed.
|
3
|
+
* Added a file-temp.rb file for convenience.
|
4
|
+
* The gem tasks in the Rakefile now assume Rubygems 2.x.
|
5
|
+
* Some gemspec updates, removed rubyforge_project, added a cert.
|
6
|
+
* Skip one test on OSX since it's an issue with the underlying C function.
|
7
|
+
* Reorganized internal directory layout so Windows, Unix and Java versions
|
8
|
+
are each in their own directory and have their own versions for ease
|
9
|
+
of maintenance.
|
10
|
+
|
1
11
|
= 1.2.1 - 17-Feb-2014
|
2
12
|
* There is now a completely separate implementation for JRuby that uses the
|
3
13
|
Java API instead of C. It uses a GUID to create the temporary file name
|
data/MANIFEST
CHANGED
@@ -3,7 +3,10 @@
|
|
3
3
|
* README
|
4
4
|
* Rakefile
|
5
5
|
* file-temp.gemspec
|
6
|
+
* certs/djberg96_pub.pem
|
7
|
+
* lib/file-temp.rb
|
6
8
|
* lib/file/temp.rb
|
7
|
-
* lib/file/
|
8
|
-
* lib/file/
|
9
|
+
* lib/file/java/temp.rb
|
10
|
+
* lib/file/unix/temp.rb
|
11
|
+
* lib/file/windows/temp.rb
|
9
12
|
* test/test_file_temp.rb
|
data/README
CHANGED
@@ -42,11 +42,15 @@
|
|
42
42
|
== MS Windows
|
43
43
|
You may need to use the mingw build in order to use this library.
|
44
44
|
|
45
|
+
Also, there was a bug with GetTempFileName function on certain versions
|
46
|
+
of MS Windows that may cause a failure. However, if you'r patched up you
|
47
|
+
should not see it.
|
48
|
+
|
45
49
|
== License
|
46
50
|
Artistic 2.0
|
47
51
|
|
48
52
|
== Copyright
|
49
|
-
(C) 2007-
|
53
|
+
(C) 2007-2016 Daniel J. Berger
|
50
54
|
All Rights Reserved
|
51
55
|
|
52
56
|
== Warranty
|
data/Rakefile
CHANGED
@@ -8,19 +8,16 @@ CLEAN.include('**/*.rbc', '**/*.gem', '**/*.tmp')
|
|
8
8
|
namespace 'gem' do
|
9
9
|
desc 'Create the file-temp gem'
|
10
10
|
task :create => [:clean] do
|
11
|
+
require 'rubygems/package'
|
11
12
|
spec = eval(IO.read('file-temp.gemspec'))
|
12
|
-
|
13
|
-
|
14
|
-
else
|
15
|
-
require 'rubygems/package'
|
16
|
-
Gem::Package.build(spec)
|
17
|
-
end
|
13
|
+
spec.signing_key = File.join(Dir.home, '.ssh', 'gem-private_key.pem')
|
14
|
+
Gem::Package.build(spec, true)
|
18
15
|
end
|
19
16
|
|
20
17
|
desc 'Install the file-temp gem'
|
21
18
|
task :install => [:create] do
|
22
19
|
file = Dir["*.gem"].first
|
23
|
-
sh "gem install #{file}"
|
20
|
+
sh "gem install -l #{file}"
|
24
21
|
end
|
25
22
|
end
|
26
23
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
|
3
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
4
|
+
MB4XDTE1MDkwMjIwNDkxOFoXDTE2MDkwMTIwNDkxOFowPzERMA8GA1UEAwwIZGpi
|
5
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
6
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyTkvXqRp6hLs9eoJOS
|
7
|
+
Hmi8kRYbq9Vkf15/hMxJpotYMgJVHHWrmDcC5Dye2PbnXjTkKf266Zw0PtT9h+lI
|
8
|
+
S3ts9HO+vaCFSMwFFZmnWJSpQ3CNw2RcHxjWkk9yF7imEM8Kz9ojhiDXzBetdV6M
|
9
|
+
gr0lV/alUr7TNVBDngbXEfTWscyXh1qd7xZ4EcOdsDktCe5G45N/o3662tPQvJsi
|
10
|
+
FOF0CM/KuBsa/HL1/eoEmF4B3EKIRfTHrQ3hu20Kv3RJ88QM4ec2+0dd97uX693O
|
11
|
+
zv6981fyEg+aXLkxrkViM/tz2qR2ZE0jPhHTREPYeMEgptRkTmWSKAuLVWrJEfgl
|
12
|
+
DtkCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEwe
|
13
|
+
nn6bfJADmuIDiMSOzedOrL+xMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
|
14
|
+
bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
15
|
+
ggEBAHmNOCWoDVD75zHFueY0viwGDVP1BNGFC+yXcb7u2GlK+nEMCORqzURbYPf7
|
16
|
+
tL+/hzmePIRz7i30UM//64GI1NLv9jl7nIwjhPpXpf7/lu2I9hOTsvwSumb5UiKC
|
17
|
+
/sqBxI3sfj9pr79Wpv4MuikX1XPik7Ncb7NPsJPw06Lvyc3Hkg5X2XpPtLtS+Gr2
|
18
|
+
wKJnmzb5rIPS1cmsqv0M9LPWflzfwoZ/SpnmhagP+g05p8bRNKjZSA2iImM/GyYZ
|
19
|
+
EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
|
20
|
+
tGSHgAmcLlkdGgan182qsE/4kKM=
|
21
|
+
-----END CERTIFICATE-----
|
data/file-temp.gemspec
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
|
3
3
|
Gem::Specification.new do |spec|
|
4
|
-
spec.name
|
5
|
-
spec.version
|
6
|
-
spec.author
|
7
|
-
spec.license
|
8
|
-
spec.email
|
9
|
-
spec.homepage
|
10
|
-
spec.summary
|
11
|
-
spec.test_file
|
12
|
-
spec.files
|
4
|
+
spec.name = 'file-temp'
|
5
|
+
spec.version = '1.3.0'
|
6
|
+
spec.author = 'Daniel J. Berger'
|
7
|
+
spec.license = 'Artistic 2.0'
|
8
|
+
spec.email = 'djberg96@gmail.com'
|
9
|
+
spec.homepage = 'http://github.com/djberg96/file-temp'
|
10
|
+
spec.summary = 'An alternative way to generate temp files'
|
11
|
+
spec.test_file = 'test/test_file_temp.rb'
|
12
|
+
spec.files = Dir['**/*'].delete_if{ |item| item.include?('git') }
|
13
|
+
spec.cert_chain = Dir['certs/*']
|
13
14
|
|
14
15
|
spec.extra_rdoc_files = ['CHANGES', 'README', 'MANIFEST']
|
15
|
-
spec.rubyforge_project = 'shards'
|
16
|
-
spec.required_ruby_version = '>= 1.8.6'
|
17
16
|
|
18
17
|
spec.add_dependency('ffi', '>= 1.0.0')
|
19
18
|
spec.add_development_dependency('test-unit')
|
data/lib/file-temp.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'file/temp'
|
@@ -3,7 +3,7 @@ import java.lang.System
|
|
3
3
|
|
4
4
|
class File::Temp < File
|
5
5
|
# The version of the file-temp library.
|
6
|
-
VERSION = '1.
|
6
|
+
VERSION = '1.3.0'
|
7
7
|
|
8
8
|
# The temporary directory used on MS Windows or Unix.
|
9
9
|
TMPDIR = java.lang.System.getProperties["java.io.tmpdir"]
|
@@ -51,9 +51,10 @@ class File::Temp < File
|
|
51
51
|
|
52
52
|
@file.deleteOnExit if delete
|
53
53
|
|
54
|
-
|
54
|
+
path = @file.getName
|
55
|
+
super(path, 'wb+')
|
55
56
|
|
56
|
-
|
57
|
+
@path = path unless delete
|
57
58
|
end
|
58
59
|
|
59
60
|
# Generates a unique file name.
|
data/lib/file/temp.rb
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
if RUBY_PLATFORM == 'java'
|
2
|
-
|
2
|
+
require_relative 'java/temp'
|
3
3
|
else
|
4
|
-
|
4
|
+
if File::ALT_SEPARATOR
|
5
|
+
require_relative 'windows/temp'
|
6
|
+
else
|
7
|
+
require_relative 'unix/temp'
|
8
|
+
end
|
5
9
|
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class File::Temp < File
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib FFI::Library::LIBC
|
7
|
+
|
8
|
+
# :stopdoc:
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
attach_function :fclose, [:pointer], :int
|
13
|
+
attach_function :_fileno, :fileno, [:pointer], :int
|
14
|
+
attach_function :strerror, [:int], :string
|
15
|
+
attach_function :tmpfile, [], :pointer
|
16
|
+
attach_function :tmpnam, [:pointer], :string
|
17
|
+
attach_function :mktemp, [:pointer], :string
|
18
|
+
|
19
|
+
private_class_method :mktemp, :strerror, :tmpfile
|
20
|
+
private_class_method :tmpnam, :fclose, :_fileno
|
21
|
+
|
22
|
+
public
|
23
|
+
|
24
|
+
# :startdoc:
|
25
|
+
|
26
|
+
# The version of the file-temp library.
|
27
|
+
VERSION = '1.3.0'
|
28
|
+
|
29
|
+
# The temporary directory used on MS Windows or Unix.
|
30
|
+
TMPDIR = ENV['TEMP'] || ENV['TMP'] || ENV['TMPDIR'] || Dir.tmpdir
|
31
|
+
|
32
|
+
# The name of the temporary file. Set to nil if the +delete+ option to the
|
33
|
+
# constructor is true.
|
34
|
+
attr_reader :path
|
35
|
+
|
36
|
+
# Creates a new, anonymous, temporary file in your File::Temp::TMPDIR
|
37
|
+
# directory
|
38
|
+
#
|
39
|
+
# If the +delete+ option is set to true (the default) then the temporary file
|
40
|
+
# will be deleted automatically as soon as all references to it are closed.
|
41
|
+
# Otherwise, the file will live on in your File::Temp::TMPDIR path.
|
42
|
+
#
|
43
|
+
# If the +delete+ option is set to false, then the file is not deleted. In
|
44
|
+
# addition, you can supply a string +template+ that the system replaces with
|
45
|
+
# a unique filename. This template should end with 3 to 6 'X' characters.
|
46
|
+
# The default template is 'rb_file_temp_XXXXXX'. In this case the temporary
|
47
|
+
# file lives in the directory where it was created.
|
48
|
+
#
|
49
|
+
# The +template+ argument is ignored if the +delete+ argument is true.
|
50
|
+
#
|
51
|
+
# Example:
|
52
|
+
#
|
53
|
+
# fh = File::Temp.new(true, 'rb_file_temp_XXXXXX') => file
|
54
|
+
# fh.puts 'hello world'
|
55
|
+
# fh.close
|
56
|
+
#
|
57
|
+
def initialize(delete = true, template = 'rb_file_temp_XXXXXX')
|
58
|
+
@fptr = nil
|
59
|
+
|
60
|
+
if delete
|
61
|
+
@fptr = tmpfile()
|
62
|
+
fd = _fileno(@fptr)
|
63
|
+
else
|
64
|
+
begin
|
65
|
+
omask = File.umask(077)
|
66
|
+
|
67
|
+
ptr = FFI::MemoryPointer.from_string(template)
|
68
|
+
|
69
|
+
str = mktemp(ptr)
|
70
|
+
|
71
|
+
if str.nil? || str.empty?
|
72
|
+
raise SystemCallError.new('mktemp', FFI.errno)
|
73
|
+
end
|
74
|
+
|
75
|
+
@path = File.join(TMPDIR, ptr.read_string)
|
76
|
+
ensure
|
77
|
+
File.umask(omask)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
if delete
|
82
|
+
super(fd, 'wb+')
|
83
|
+
else
|
84
|
+
super(@path, 'wb+')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# The close method was overridden to ensure the internal file pointer we
|
89
|
+
# created in the constructor is closed. It is otherwise identical to the
|
90
|
+
# File#close method.
|
91
|
+
#
|
92
|
+
def close
|
93
|
+
super
|
94
|
+
fclose(@fptr) if @fptr
|
95
|
+
end
|
96
|
+
|
97
|
+
# Generates a unique file name.
|
98
|
+
#
|
99
|
+
# Note that a file is not actually generated on the filesystem.
|
100
|
+
#
|
101
|
+
def self.temp_name
|
102
|
+
tmpnam(nil) << '.tmp'
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,219 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
class File::Temp < File
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib FFI::Library::LIBC
|
7
|
+
|
8
|
+
# :stopdoc:
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
attach_function :_close, [:int], :int
|
13
|
+
attach_function :fclose, [:pointer], :int
|
14
|
+
attach_function :_fdopen, [:int, :string], :pointer
|
15
|
+
attach_function :_fileno, [:pointer], :int
|
16
|
+
attach_function :_get_errno, [:pointer], :int
|
17
|
+
attach_function :_open, [:string, :int, :int], :int
|
18
|
+
attach_function :_open_osfhandle, [:long, :int], :int
|
19
|
+
attach_function :tmpnam_s, [:pointer, :size_t], :int
|
20
|
+
attach_function :mktemp_s, :_mktemp_s, [:pointer, :size_t], :int
|
21
|
+
|
22
|
+
private_class_method :_close, :fclose, :_fdopen, :_fileno, :_get_errno
|
23
|
+
private_class_method :_open, :_open_osfhandle, :mktemp_s, :tmpnam_s
|
24
|
+
|
25
|
+
ffi_lib :kernel32
|
26
|
+
|
27
|
+
attach_function :CloseHandle, [:long], :bool
|
28
|
+
attach_function :CreateFileW, [:buffer_in, :ulong, :ulong, :pointer, :ulong, :ulong, :ulong], :long
|
29
|
+
attach_function :DeleteFileW, [:string], :bool
|
30
|
+
attach_function :GetTempPathW, [:ulong, :buffer_out], :ulong
|
31
|
+
attach_function :GetTempFileNameW, [:buffer_in, :string, :uint, :buffer_out], :uint
|
32
|
+
|
33
|
+
private_class_method :_close, :_fdopen, :_open, :_open_osfhandle
|
34
|
+
private_class_method :CloseHandle, :CreateFileW, :DeleteFileW
|
35
|
+
private_class_method :GetTempPathW, :GetTempFileNameW
|
36
|
+
|
37
|
+
S_IWRITE = 128
|
38
|
+
S_IREAD = 256
|
39
|
+
BINARY = 0x8000
|
40
|
+
SHORT_LIVED = 0x1000
|
41
|
+
GENERIC_READ = 0x80000000
|
42
|
+
GENERIC_WRITE = 0x40000000
|
43
|
+
CREATE_ALWAYS = 2
|
44
|
+
|
45
|
+
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
46
|
+
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000
|
47
|
+
|
48
|
+
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
49
|
+
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
50
|
+
INVALID_HANDLE_VALUE = -1
|
51
|
+
|
52
|
+
public
|
53
|
+
|
54
|
+
# :startdoc:
|
55
|
+
|
56
|
+
# The version of the file-temp library.
|
57
|
+
VERSION = '1.3.0'
|
58
|
+
|
59
|
+
# The temporary directory used on MS Windows or Unix.
|
60
|
+
TMPDIR = ENV['TEMP'] || ENV['TMP'] || ENV['USERPROFILE'] || Dir.tmpdir
|
61
|
+
|
62
|
+
# The name of the temporary file. Set to nil if the +delete+ option to the
|
63
|
+
# constructor is true.
|
64
|
+
attr_reader :path
|
65
|
+
|
66
|
+
# Creates a new, anonymous, temporary file in your File::Temp::TMPDIR
|
67
|
+
# directory
|
68
|
+
#
|
69
|
+
# If the +delete+ option is set to true (the default) then the temporary file
|
70
|
+
# will be deleted automatically as soon as all references to it are closed.
|
71
|
+
# Otherwise, the file will live on in your File::Temp::TMPDIR path.
|
72
|
+
#
|
73
|
+
# If the +delete+ option is set to false, then the file is not deleted. In
|
74
|
+
# addition, you can supply a string +template+ that the system replaces with
|
75
|
+
# a unique filename. This template should end with 3 to 6 'X' characters.
|
76
|
+
# The default template is 'rb_file_temp_XXXXXX'. In this case the temporary
|
77
|
+
# file lives in the directory where it was created.
|
78
|
+
#
|
79
|
+
# The +template+ argument is ignored if the +delete+ argument is true.
|
80
|
+
#
|
81
|
+
# Example:
|
82
|
+
#
|
83
|
+
# fh = File::Temp.new(true, 'rb_file_temp_XXXXXX') => file
|
84
|
+
# fh.puts 'hello world'
|
85
|
+
# fh.close
|
86
|
+
#
|
87
|
+
def initialize(delete = true, template = 'rb_file_temp_XXXXXX')
|
88
|
+
@fptr = nil
|
89
|
+
|
90
|
+
if delete
|
91
|
+
@fptr = tmpfile()
|
92
|
+
fd = _fileno(@fptr)
|
93
|
+
else
|
94
|
+
begin
|
95
|
+
omask = File.umask(077)
|
96
|
+
|
97
|
+
ptr = FFI::MemoryPointer.from_string(template)
|
98
|
+
|
99
|
+
errno = mktemp_s(ptr, ptr.size)
|
100
|
+
|
101
|
+
raise SystemCallError.new('mktemp_s', errno) if errno != 0
|
102
|
+
|
103
|
+
@path = File.join(TMPDIR, ptr.read_string)
|
104
|
+
@path.tr!(File::SEPARATOR, File::ALT_SEPARATOR)
|
105
|
+
ensure
|
106
|
+
File.umask(omask)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
if delete
|
111
|
+
super(fd, 'wb+')
|
112
|
+
else
|
113
|
+
super(@path, 'wb+')
|
114
|
+
end
|
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.
|
127
|
+
#
|
128
|
+
# Note that a file is not actually generated on the filesystem.
|
129
|
+
#--
|
130
|
+
# NOTE: One quirk of the Windows function is that, after the first call, it
|
131
|
+
# adds a file extension of sequential numbers in base 32, e.g. .1-.1vvvvvu.
|
132
|
+
#
|
133
|
+
def self.temp_name
|
134
|
+
ptr = FFI::MemoryPointer.new(:char, 1024)
|
135
|
+
errno = tmpnam_s(ptr, ptr.size)
|
136
|
+
|
137
|
+
raise SystemCallError.new('tmpnam_s', errno) if errno != 0
|
138
|
+
|
139
|
+
TMPDIR + ptr.read_string + 'tmp'
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
# For those times when we want the posix errno rather than a formatted string.
|
145
|
+
# This is necessary because FFI.errno appears to be using GetLastError() which
|
146
|
+
# does not always match what _get_errno() returns.
|
147
|
+
#
|
148
|
+
def get_posix_errno
|
149
|
+
ptr = FFI::MemoryPointer.new(:int)
|
150
|
+
_get_errno(ptr)
|
151
|
+
ptr.read_int
|
152
|
+
end
|
153
|
+
|
154
|
+
# Simple wrapper around the GetTempPath function.
|
155
|
+
#
|
156
|
+
def get_temp_path
|
157
|
+
buf = 0.chr * 1024
|
158
|
+
buf.encode!("UTF-16LE")
|
159
|
+
|
160
|
+
if GetTempPathW(buf.size, buf) == 0
|
161
|
+
raise SystemCallError, FFI.errno, 'GetTempPathW'
|
162
|
+
end
|
163
|
+
|
164
|
+
buf.strip.chop # remove trailing slash
|
165
|
+
end
|
166
|
+
|
167
|
+
# The version of tmpfile() implemented by Microsoft is unacceptable.
|
168
|
+
# It attempts to write to C:\ (root) instead of a temporary directory.
|
169
|
+
# This is not only bad behavior, it won't work on Windows 7 and later
|
170
|
+
# without admin rights due to security restrictions.
|
171
|
+
#
|
172
|
+
# This is a custom implementation based on some code from the Cairo
|
173
|
+
# project.
|
174
|
+
#
|
175
|
+
def tmpfile
|
176
|
+
file_name = get_temp_path()
|
177
|
+
buf = 0.chr * 1024
|
178
|
+
buf.encode!("UTF-16LE")
|
179
|
+
|
180
|
+
if GetTempFileNameW(file_name, 'rb_', 0, buf) == 0
|
181
|
+
raise SystemCallError, FFI.errno, 'GetTempFileNameW'
|
182
|
+
end
|
183
|
+
|
184
|
+
file_name = buf.strip
|
185
|
+
|
186
|
+
handle = CreateFileW(
|
187
|
+
file_name,
|
188
|
+
GENERIC_READ | GENERIC_WRITE,
|
189
|
+
0,
|
190
|
+
nil,
|
191
|
+
CREATE_ALWAYS,
|
192
|
+
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
|
193
|
+
0
|
194
|
+
)
|
195
|
+
|
196
|
+
if handle == INVALID_HANDLE_VALUE
|
197
|
+
error = FFI.errno
|
198
|
+
DeleteFileW(file_name)
|
199
|
+
raise SystemCallError.new('CreateFileW', error)
|
200
|
+
end
|
201
|
+
|
202
|
+
fd = _open_osfhandle(handle, 0)
|
203
|
+
|
204
|
+
if fd < 0
|
205
|
+
CloseHandle(handle)
|
206
|
+
raise SystemCallError, get_posix_errno, '_open_osfhandle'
|
207
|
+
end
|
208
|
+
|
209
|
+
fp = _fdopen(fd, 'w+b')
|
210
|
+
|
211
|
+
if fp.nil?
|
212
|
+
_close(fd)
|
213
|
+
CloseHandle(handle)
|
214
|
+
raise SystemCallError, get_posix_errno, 'fdopen'
|
215
|
+
end
|
216
|
+
|
217
|
+
fp
|
218
|
+
end
|
219
|
+
end
|
data/test/test_file_temp.rb
CHANGED
@@ -10,6 +10,7 @@ require 'file/temp'
|
|
10
10
|
|
11
11
|
class TC_File_Temp < Test::Unit::TestCase
|
12
12
|
WINDOWS = File::ALT_SEPARATOR
|
13
|
+
OSX = RbConfig::CONFIG['host_os'] =~ /darwin/i
|
13
14
|
|
14
15
|
def setup
|
15
16
|
@dir = File::Temp::TMPDIR
|
@@ -21,7 +22,7 @@ class TC_File_Temp < Test::Unit::TestCase
|
|
21
22
|
end
|
22
23
|
|
23
24
|
test "library version is set to expected value" do
|
24
|
-
assert_equal('1.
|
25
|
+
assert_equal('1.3.0', File::Temp::VERSION)
|
25
26
|
end
|
26
27
|
|
27
28
|
# Fails with JRuby, not sure why.
|
@@ -67,6 +68,7 @@ class TC_File_Temp < Test::Unit::TestCase
|
|
67
68
|
end
|
68
69
|
|
69
70
|
test "an error is raised if a custom template is invalid" do
|
71
|
+
omit_if(OSX)
|
70
72
|
assert_raise(Errno::EINVAL){ File::Temp.new(false, 'xx') }
|
71
73
|
end
|
72
74
|
|
metadata
CHANGED
@@ -1,55 +1,77 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: file-temp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
|
-
cert_chain:
|
11
|
-
|
10
|
+
cert_chain:
|
11
|
+
- |
|
12
|
+
-----BEGIN CERTIFICATE-----
|
13
|
+
MIIDcDCCAligAwIBAgIBATANBgkqhkiG9w0BAQUFADA/MREwDwYDVQQDDAhkamJl
|
14
|
+
cmc5NjEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPyLGQBGRYDY29t
|
15
|
+
MB4XDTE1MDkwMjIwNDkxOFoXDTE2MDkwMTIwNDkxOFowPzERMA8GA1UEAwwIZGpi
|
16
|
+
ZXJnOTYxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkWA2Nv
|
17
|
+
bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMyTkvXqRp6hLs9eoJOS
|
18
|
+
Hmi8kRYbq9Vkf15/hMxJpotYMgJVHHWrmDcC5Dye2PbnXjTkKf266Zw0PtT9h+lI
|
19
|
+
S3ts9HO+vaCFSMwFFZmnWJSpQ3CNw2RcHxjWkk9yF7imEM8Kz9ojhiDXzBetdV6M
|
20
|
+
gr0lV/alUr7TNVBDngbXEfTWscyXh1qd7xZ4EcOdsDktCe5G45N/o3662tPQvJsi
|
21
|
+
FOF0CM/KuBsa/HL1/eoEmF4B3EKIRfTHrQ3hu20Kv3RJ88QM4ec2+0dd97uX693O
|
22
|
+
zv6981fyEg+aXLkxrkViM/tz2qR2ZE0jPhHTREPYeMEgptRkTmWSKAuLVWrJEfgl
|
23
|
+
DtkCAwEAAaN3MHUwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEwe
|
24
|
+
nn6bfJADmuIDiMSOzedOrL+xMB0GA1UdEQQWMBSBEmRqYmVyZzk2QGdtYWlsLmNv
|
25
|
+
bTAdBgNVHRIEFjAUgRJkamJlcmc5NkBnbWFpbC5jb20wDQYJKoZIhvcNAQEFBQAD
|
26
|
+
ggEBAHmNOCWoDVD75zHFueY0viwGDVP1BNGFC+yXcb7u2GlK+nEMCORqzURbYPf7
|
27
|
+
tL+/hzmePIRz7i30UM//64GI1NLv9jl7nIwjhPpXpf7/lu2I9hOTsvwSumb5UiKC
|
28
|
+
/sqBxI3sfj9pr79Wpv4MuikX1XPik7Ncb7NPsJPw06Lvyc3Hkg5X2XpPtLtS+Gr2
|
29
|
+
wKJnmzb5rIPS1cmsqv0M9LPWflzfwoZ/SpnmhagP+g05p8bRNKjZSA2iImM/GyYZ
|
30
|
+
EJYzxdPOrx2n6NYR3Hk+vHP0U7UBSveI6+qx+ndQYaeyCn+GRX2PKS9h66YF/Q1V
|
31
|
+
tGSHgAmcLlkdGgan182qsE/4kKM=
|
32
|
+
-----END CERTIFICATE-----
|
33
|
+
date: 2016-04-09 00:00:00.000000000 Z
|
12
34
|
dependencies:
|
13
35
|
- !ruby/object:Gem::Dependency
|
14
36
|
name: ffi
|
15
37
|
requirement: !ruby/object:Gem::Requirement
|
16
38
|
requirements:
|
17
|
-
- -
|
39
|
+
- - ">="
|
18
40
|
- !ruby/object:Gem::Version
|
19
41
|
version: 1.0.0
|
20
42
|
type: :runtime
|
21
43
|
prerelease: false
|
22
44
|
version_requirements: !ruby/object:Gem::Requirement
|
23
45
|
requirements:
|
24
|
-
- -
|
46
|
+
- - ">="
|
25
47
|
- !ruby/object:Gem::Version
|
26
48
|
version: 1.0.0
|
27
49
|
- !ruby/object:Gem::Dependency
|
28
50
|
name: test-unit
|
29
51
|
requirement: !ruby/object:Gem::Requirement
|
30
52
|
requirements:
|
31
|
-
- -
|
53
|
+
- - ">="
|
32
54
|
- !ruby/object:Gem::Version
|
33
55
|
version: '0'
|
34
56
|
type: :development
|
35
57
|
prerelease: false
|
36
58
|
version_requirements: !ruby/object:Gem::Requirement
|
37
59
|
requirements:
|
38
|
-
- -
|
60
|
+
- - ">="
|
39
61
|
- !ruby/object:Gem::Version
|
40
62
|
version: '0'
|
41
63
|
- !ruby/object:Gem::Dependency
|
42
64
|
name: rake
|
43
65
|
requirement: !ruby/object:Gem::Requirement
|
44
66
|
requirements:
|
45
|
-
- -
|
67
|
+
- - ">="
|
46
68
|
- !ruby/object:Gem::Version
|
47
69
|
version: '0'
|
48
70
|
type: :development
|
49
71
|
prerelease: false
|
50
72
|
version_requirements: !ruby/object:Gem::Requirement
|
51
73
|
requirements:
|
52
|
-
- -
|
74
|
+
- - ">="
|
53
75
|
- !ruby/object:Gem::Version
|
54
76
|
version: '0'
|
55
77
|
description: |2
|
@@ -64,14 +86,24 @@ extra_rdoc_files:
|
|
64
86
|
- README
|
65
87
|
- MANIFEST
|
66
88
|
files:
|
89
|
+
- certs
|
90
|
+
- certs/djberg96_pub.pem
|
67
91
|
- CHANGES
|
68
|
-
- MANIFEST
|
69
|
-
- README
|
70
|
-
- Rakefile
|
71
92
|
- file-temp.gemspec
|
93
|
+
- lib
|
94
|
+
- lib/file
|
95
|
+
- lib/file/java
|
96
|
+
- lib/file/java/temp.rb
|
72
97
|
- lib/file/temp.rb
|
73
|
-
- lib/file/
|
74
|
-
- lib/file/
|
98
|
+
- lib/file/unix
|
99
|
+
- lib/file/unix/temp.rb
|
100
|
+
- lib/file/windows
|
101
|
+
- lib/file/windows/temp.rb
|
102
|
+
- lib/file-temp.rb
|
103
|
+
- MANIFEST
|
104
|
+
- Rakefile
|
105
|
+
- README
|
106
|
+
- test
|
75
107
|
- test/test_file_temp.rb
|
76
108
|
homepage: http://github.com/djberg96/file-temp
|
77
109
|
licenses:
|
@@ -83,17 +115,17 @@ require_paths:
|
|
83
115
|
- lib
|
84
116
|
required_ruby_version: !ruby/object:Gem::Requirement
|
85
117
|
requirements:
|
86
|
-
- -
|
118
|
+
- - ">="
|
87
119
|
- !ruby/object:Gem::Version
|
88
|
-
version:
|
120
|
+
version: '0'
|
89
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
122
|
requirements:
|
91
|
-
- -
|
123
|
+
- - ">="
|
92
124
|
- !ruby/object:Gem::Version
|
93
125
|
version: '0'
|
94
126
|
requirements: []
|
95
|
-
rubyforge_project:
|
96
|
-
rubygems_version: 2.
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 2.5.1
|
97
129
|
signing_key:
|
98
130
|
specification_version: 4
|
99
131
|
summary: An alternative way to generate temp files
|
metadata.gz.sig
ADDED
data/lib/file/temp_c.rb
DELETED
@@ -1,254 +0,0 @@
|
|
1
|
-
require 'ffi'
|
2
|
-
require 'tmpdir'
|
3
|
-
|
4
|
-
class File::Temp < File
|
5
|
-
extend FFI::Library
|
6
|
-
ffi_lib FFI::Library::LIBC
|
7
|
-
|
8
|
-
# :stopdoc:
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
if File::ALT_SEPARATOR
|
13
|
-
attach_function :_close, [:int], :int
|
14
|
-
attach_function :fclose, [:pointer], :int
|
15
|
-
attach_function :_fdopen, [:int, :string], :pointer
|
16
|
-
attach_function :_fileno, [:pointer], :int
|
17
|
-
attach_function :_get_errno, [:pointer], :int
|
18
|
-
attach_function :_open, [:string, :int, :int], :int
|
19
|
-
attach_function :_open_osfhandle, [:long, :int], :int
|
20
|
-
attach_function :tmpnam_s, [:pointer, :size_t], :int
|
21
|
-
attach_function :mktemp_s, :_mktemp_s, [:pointer, :size_t], :int
|
22
|
-
|
23
|
-
private_class_method :_close, :_fdopen, :_get_errno, :_open
|
24
|
-
private_class_method :_open_osfhandle, :mktemp_s, :tmpnam_s
|
25
|
-
|
26
|
-
ffi_lib :kernel32
|
27
|
-
|
28
|
-
attach_function :CloseHandle, [:long], :bool
|
29
|
-
attach_function :CreateFileW, [:buffer_in, :ulong, :ulong, :pointer, :ulong, :ulong, :ulong], :long
|
30
|
-
attach_function :DeleteFileW, [:string], :bool
|
31
|
-
attach_function :GetTempPathW, [:ulong, :buffer_out], :ulong
|
32
|
-
attach_function :GetTempFileNameW, [:buffer_in, :string, :uint, :buffer_out], :uint
|
33
|
-
|
34
|
-
private_class_method :_close, :_fdopen, :_open, :_open_osfhandle
|
35
|
-
private_class_method :CloseHandle, :CreateFileW, :DeleteFileW
|
36
|
-
private_class_method :GetTempPathW, :GetTempFileNameW
|
37
|
-
|
38
|
-
S_IWRITE = 128
|
39
|
-
S_IREAD = 256
|
40
|
-
BINARY = 0x8000
|
41
|
-
SHORT_LIVED = 0x1000
|
42
|
-
GENERIC_READ = 0x80000000
|
43
|
-
GENERIC_WRITE = 0x40000000
|
44
|
-
CREATE_ALWAYS = 2
|
45
|
-
|
46
|
-
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000
|
47
|
-
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000
|
48
|
-
|
49
|
-
FILE_ATTRIBUTE_NORMAL = 0x00000080
|
50
|
-
FILE_FLAG_DELETE_ON_CLOSE = 0x04000000
|
51
|
-
INVALID_HANDLE_VALUE = -1
|
52
|
-
else
|
53
|
-
attach_function :fclose, [:pointer], :int
|
54
|
-
attach_function :_fileno, :fileno, [:pointer], :int
|
55
|
-
attach_function :strerror, [:int], :string
|
56
|
-
attach_function :tmpfile, [], :pointer
|
57
|
-
attach_function :tmpnam, [:pointer], :string
|
58
|
-
attach_function :mktemp, [:pointer], :string
|
59
|
-
|
60
|
-
private_class_method :mktemp, :strerror, :tmpfile, :tmpnam
|
61
|
-
end
|
62
|
-
|
63
|
-
private_class_method :fclose, :_fileno
|
64
|
-
|
65
|
-
public
|
66
|
-
|
67
|
-
# :startdoc:
|
68
|
-
|
69
|
-
# The version of the file-temp library.
|
70
|
-
VERSION = '1.2.1'
|
71
|
-
|
72
|
-
# The temporary directory used on MS Windows or Unix.
|
73
|
-
if File::ALT_SEPARATOR
|
74
|
-
TMPDIR = ENV['TEMP'] || ENV['TMP'] || ENV['USERPROFILE'] || Dir.tmpdir
|
75
|
-
else
|
76
|
-
TMPDIR = ENV['TEMP'] || ENV['TMP'] || ENV['TMPDIR'] || Dir.tmpdir
|
77
|
-
end
|
78
|
-
|
79
|
-
# The name of the temporary file. Set to nil if the +delete+ option to the
|
80
|
-
# constructor is true.
|
81
|
-
attr_reader :path
|
82
|
-
|
83
|
-
# Creates a new, anonymous, temporary file in your File::Temp::TMPDIR
|
84
|
-
# directory
|
85
|
-
#
|
86
|
-
# If the +delete+ option is set to true (the default) then the temporary file
|
87
|
-
# will be deleted automatically as soon as all references to it are closed.
|
88
|
-
# Otherwise, the file will live on in your File::Temp::TMPDIR path.
|
89
|
-
#
|
90
|
-
# If the +delete+ option is set to false, then the file is not deleted. In
|
91
|
-
# addition, you can supply a string +template+ that the system replaces with
|
92
|
-
# a unique filename. This template should end with 3 to 6 'X' characters.
|
93
|
-
# The default template is 'rb_file_temp_XXXXXX'. In this case the temporary
|
94
|
-
# file lives in the directory where it was created.
|
95
|
-
#
|
96
|
-
# The +template+ argument is ignored if the +delete+ argument is true.
|
97
|
-
#
|
98
|
-
# Example:
|
99
|
-
#
|
100
|
-
# fh = File::Temp.new(true, 'rb_file_temp_XXXXXX') => file
|
101
|
-
# fh.puts 'hello world'
|
102
|
-
# fh.close
|
103
|
-
#
|
104
|
-
def initialize(delete = true, template = 'rb_file_temp_XXXXXX')
|
105
|
-
@fptr = nil
|
106
|
-
|
107
|
-
if delete
|
108
|
-
@fptr = tmpfile()
|
109
|
-
fd = _fileno(@fptr)
|
110
|
-
else
|
111
|
-
begin
|
112
|
-
omask = File.umask(077)
|
113
|
-
|
114
|
-
ptr = FFI::MemoryPointer.from_string(template)
|
115
|
-
|
116
|
-
if File::ALT_SEPARATOR
|
117
|
-
errno = mktemp_s(ptr, ptr.size)
|
118
|
-
|
119
|
-
raise SystemCallError.new('mktemp_s', errno) if errno != 0
|
120
|
-
else
|
121
|
-
str = mktemp(ptr)
|
122
|
-
|
123
|
-
if str.nil? || str.empty?
|
124
|
-
raise SystemCallError.new('mktemp', FFI.errno)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
@path = File.join(TMPDIR, ptr.read_string)
|
129
|
-
@path.tr!(File::SEPARATOR, File::ALT_SEPARATOR) if File::ALT_SEPARATOR
|
130
|
-
ensure
|
131
|
-
File.umask(omask)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
if delete
|
136
|
-
super(fd, 'wb+')
|
137
|
-
else
|
138
|
-
super(@path, 'wb+')
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# The close method was overridden to ensure the internal file pointer we
|
143
|
-
# created in the constructor is closed. It is otherwise identical to the
|
144
|
-
# File#close method.
|
145
|
-
#
|
146
|
-
def close
|
147
|
-
super
|
148
|
-
fclose(@fptr) if @fptr
|
149
|
-
end
|
150
|
-
|
151
|
-
# Generates a unique file name.
|
152
|
-
#
|
153
|
-
# Note that a file is not actually generated on the filesystem.
|
154
|
-
#--
|
155
|
-
# NOTE: One quirk of the Windows function is that, after the first call, it
|
156
|
-
# adds a file extension of sequential numbers in base 32, e.g. .1-.1vvvvvu.
|
157
|
-
#
|
158
|
-
def self.temp_name
|
159
|
-
if File::ALT_SEPARATOR
|
160
|
-
ptr = FFI::MemoryPointer.new(:char, 1024)
|
161
|
-
errno = tmpnam_s(ptr, ptr.size)
|
162
|
-
|
163
|
-
raise SystemCallError.new('tmpnam_s', errno) if errno != 0
|
164
|
-
|
165
|
-
TMPDIR + ptr.read_string + 'tmp'
|
166
|
-
else
|
167
|
-
tmpnam(nil) << '.tmp'
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
private
|
172
|
-
|
173
|
-
# For those times when we want the posix errno rather than a formatted string.
|
174
|
-
# This is necessary because FFI.errno appears to be using GetLastError() which
|
175
|
-
# does not always match what _get_errno() returns.
|
176
|
-
#
|
177
|
-
def get_posix_errno
|
178
|
-
if File::ALT_SEPARATOR
|
179
|
-
ptr = FFI::MemoryPointer.new(:int)
|
180
|
-
_get_errno(ptr)
|
181
|
-
ptr.read_int
|
182
|
-
else
|
183
|
-
FFI.errno
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
if File::ALT_SEPARATOR
|
188
|
-
# Simple wrapper around the GetTempPath function.
|
189
|
-
#
|
190
|
-
def get_temp_path
|
191
|
-
buf = 0.chr * 1024
|
192
|
-
buf.encode!("UTF-16LE")
|
193
|
-
|
194
|
-
if GetTempPathW(buf.size, buf) == 0
|
195
|
-
raise SystemCallError, FFI.errno, 'GetTempPathW'
|
196
|
-
end
|
197
|
-
|
198
|
-
buf.strip.chop # remove trailing slash
|
199
|
-
end
|
200
|
-
|
201
|
-
# The version of tmpfile() implemented by Microsoft is unacceptable.
|
202
|
-
# It attempts to write to C:\ (root) instead of a temporary directory.
|
203
|
-
# This is not only bad behavior, it won't work on Windows 7 and later
|
204
|
-
# without admin rights due to security restrictions.
|
205
|
-
#
|
206
|
-
# This is a custom implementation based on some code from the Cairo
|
207
|
-
# project.
|
208
|
-
#
|
209
|
-
def tmpfile
|
210
|
-
file_name = get_temp_path()
|
211
|
-
buf = 0.chr * 1024
|
212
|
-
buf.encode!("UTF-16LE")
|
213
|
-
|
214
|
-
if GetTempFileNameW(file_name, 'rb_', 0, buf) == 0
|
215
|
-
raise SystemCallError, FFI.errno, 'GetTempFileNameW'
|
216
|
-
end
|
217
|
-
|
218
|
-
file_name = buf.strip
|
219
|
-
|
220
|
-
handle = CreateFileW(
|
221
|
-
file_name,
|
222
|
-
GENERIC_READ | GENERIC_WRITE,
|
223
|
-
0,
|
224
|
-
nil,
|
225
|
-
CREATE_ALWAYS,
|
226
|
-
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
|
227
|
-
0
|
228
|
-
)
|
229
|
-
|
230
|
-
if handle == INVALID_HANDLE_VALUE
|
231
|
-
error = FFI.errno
|
232
|
-
DeleteFileW(file_name)
|
233
|
-
raise SystemCallError.new('CreateFileW', error)
|
234
|
-
end
|
235
|
-
|
236
|
-
fd = _open_osfhandle(handle, 0)
|
237
|
-
|
238
|
-
if fd < 0
|
239
|
-
CloseHandle(handle)
|
240
|
-
raise SystemCallError, get_posix_errno, '_open_osfhandle'
|
241
|
-
end
|
242
|
-
|
243
|
-
fp = _fdopen(fd, 'w+b')
|
244
|
-
|
245
|
-
if fp.nil?
|
246
|
-
_close(fd)
|
247
|
-
CloseHandle(handle)
|
248
|
-
raise SystemCallError, get_posix_errno, 'fdopen'
|
249
|
-
end
|
250
|
-
|
251
|
-
fp
|
252
|
-
end
|
253
|
-
end
|
254
|
-
end
|