class File::Temp
Constants
- TMPDIR
The temporary directory used on MS Windows or Unix.
- VERSION
The version of the file-temp library
Attributes
The name of the temporary file.
Public Class Methods
Creates a new, anonymous, temporary file in your system's temporary directory, or whichever directory you specify.
If the delete
option is set to true (the default) then the temporary file will be deleted automatically as soon as all references to it are closed. Otherwise, the file will live on in your File::Temp::TMPDIR
path.
If the delete
option is set to false, then the file is not deleted. In addition, you can supply a string template
that the system replaces with a unique filename. This template should end with 3 to 6 'X' characters. The default template is 'rb_file_temp_XXXXXX'. In this case the temporary file lives in the directory where it was created.
Note that when using JRuby the template naming is not as strict, and the trailing 'X' characters are simply replaced with the GUID that Java generates for unique file names.
Example:
fh = File::Temp.new(delete: true, template: 'rb_file_temp_XXXXXX') fh.puts 'hello world' fh.close
# File lib/file/java/temp.rb, line 34 def initialize(delete: true, template: 'rb_file_temp_XXXXXX', directory: TMPDIR, **options) raise TypeError unless template.is_a?(String) # Since Java uses a GUID extension to generate a unique file name # we'll simply chop off the 'X' characters and let Java do the rest. template = template.sub(/_X{1,6}/, '_') # For consistency between implementations, convert errors here # to Errno::EINVAL. begin @file = java.io.File.createTempFile(template, nil, java.io.File.new(directory)) rescue NativeException => err raise SystemCallError.new(22), template # 22 is EINVAL end @file.deleteOnExit if delete options[:mode] ||= 'wb+' path = @file.getName super(path, **options) @path = path unless delete end
Generates a unique file name based on your tmpdir, or whichever directory you specify.
# File lib/file/java/temp.rb, line 61 def self.temp_name(directory = TMPDIR) file = java.io.File.createTempFile('rb_file_temp_', nil, java.io.File.new(directory)) file.deleteOnExit directory + file.getName end
Public Instance Methods
Identical to the File#close method except that we also finalize the underlying Java File
object.
# File lib/file/java/temp.rb, line 70 def close super @file.finalize end
Private Instance Methods
For those times when we want the posix errno rather than a formatted string. This is necessary because FFI.errno appears to be using GetLastError() which does not always match what _get_errno() returns.
# File lib/file/windows/temp.rb, line 146 def get_posix_errno ptr = FFI::MemoryPointer.new(:int) _get_errno(ptr) ptr.read_int end
Simple wrapper around the GetTempPath function.
# File lib/file/windows/temp.rb, line 154 def get_temp_path buf = 0.chr * 1024 buf.encode!("UTF-16LE") if GetTempPathW(buf.size, buf) == 0 raise SystemCallError, FFI.errno, 'GetTempPathW' end buf.strip.chop # remove trailing slash end
The version of tmpfile() implemented by Microsoft is unacceptable. It attempts to write to C:\ (root) instead of a temporary directory. This is not only bad behavior, it won't work on Windows 7 and later without admin rights due to security restrictions.
This is a custom implementation based on some code from the Cairo project.
# File lib/file/windows/temp.rb, line 173 def tmpfile file_name = get_temp_path() buf = 0.chr * 1024 buf.encode!("UTF-16LE") if GetTempFileNameW(file_name, 'rb_', 0, buf) == 0 raise SystemCallError, FFI.errno, 'GetTempFileNameW' end file_name = buf.strip handle = CreateFileW( file_name, GENERIC_READ | GENERIC_WRITE, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE, 0 ) if handle == INVALID_HANDLE_VALUE error = FFI.errno DeleteFileW(file_name) raise SystemCallError.new('CreateFileW', error) end fd = _open_osfhandle(handle, 0) if fd < 0 CloseHandle(handle) raise SystemCallError, get_posix_errno, '_open_osfhandle' end fp = _fdopen(fd, 'w+b') if fp.nil? _close(fd) CloseHandle(handle) raise SystemCallError, get_posix_errno, 'fdopen' end fp end