class File::Temp

Constants

TMPDIR

The temporary directory used on MS Windows or Unix.

VERSION

The version of the file-temp library

Attributes

path[R]

The name of the temporary file.

Public Class Methods

new(delete: true, template: 'rb_file_temp_XXXXXX', directory: TMPDIR, **options) click to toggle source

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
Calls superclass method
# 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
temp_name(directory = TMPDIR) click to toggle source

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

close() click to toggle source

Identical to the File#close method except that we also finalize the underlying Java File object.

Calls superclass method
# File lib/file/java/temp.rb, line 70
def close
  super
  @file.finalize
end

Private Instance Methods

get_posix_errno() click to toggle source

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
get_temp_path() click to toggle source

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
tmpfile() click to toggle source

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