class File

Constants

WIN32_FILE_VERSION

The version of the win32-file library

Public Class Methods

atime(file, time = nil) click to toggle source

Returns the file's last access time. If a time argument is provided, it sets the file's access time. The time argument may be a Time object or a numeric value.

# File lib/win32/file.rb, line 374
def self.atime(file, time = nil)
  set_filetime(file, nil, time) if time
  File::Stat.new(file).atime
end
basename(file, suffix = nil) click to toggle source

Returns the last component of the filename given in filename. If suffix is given and present at the end of filename, it is removed. Any extension can be removed by giving an extension of “.*”.

This was reimplemented because the current version does not handle UNC paths properly, i.e. it should not return anything less than the root. In most other respects it is identical to the current implementation, except that it does not strip the drive letter on a root path.

Unlike MRI, this version will convert all forward slashes to backslashes automatically.

Examples:

File.basename("C:\\foo\\bar.txt")         -> "bar.txt"
File.basename("C:\\foo\\bar.txt", ".txt") -> "bar"
File.basename("\\\\foo\\bar")             -> "\\\\foo\\bar"
# File lib/win32/file.rb, line 52
def self.basename(file, suffix = nil)
  file = string_check(file)
  suffix = string_check(suffix) if suffix

  return file if file.empty? # Return an empty path as-is.

  encoding = file.encoding
  wfile = file.wincode

  # Return a root path as-is.
  if PathIsRootW(wfile)
    return file.tr(File::ALT_SEPARATOR, File::SEPARATOR)
  end

  ptr = FFI::MemoryPointer.from_string(wfile)

  PathStripPathW(ptr) # Gives us the basename

  if suffix
    if suffix == '.*'
      PathRemoveExtensionW(ptr)
    else
      ext = PathFindExtensionW(ptr).read_string(suffix.length * 2).wstrip

      if ext == suffix
        PathRemoveExtensionW(ptr)
      end
    end
  end

  wfile = ptr.read_bytes(wfile.size * 2).split("\000\000").first.tr(0.chr, '')
  file = wfile.encode(encoding)[/^[^\0]*/]
  file.sub!(/\\+\z/, '') # Trim trailing slashes

  ptr.free

  file
end
blksize(file) click to toggle source

Returns the filesystem's block size.

# File lib/win32/file.rb, line 381
def self.blksize(file)
  File::Stat.new(file).blksize
end
blockdev?(file) click to toggle source

Returns whether or not the file is a block device. For MS Windows a block device is a removable drive, cdrom or ramdisk.

# File lib/win32/file.rb, line 388
def self.blockdev?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).blockdev?
end
chardev?(file) click to toggle source

Returns whether or not the file is a character device.

# File lib/win32/file.rb, line 395
def self.chardev?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).chardev?
end
ctime(file, time = nil) click to toggle source

Returns the file's creation time. If a time argument is provided, it sets the file's creation time. The time argument may be a Time object or a numeric value.

# File lib/win32/file.rb, line 404
def self.ctime(file, time = nil)
  set_filetime(file, time) if time
  File::Stat.new(file).ctime
end
directory?(file) click to toggle source

Returns whether or not the file is a directory.

# File lib/win32/file.rb, line 411
def self.directory?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).directory?
end
dirname(file) click to toggle source

Returns all components of the filename given in filename except the last one.

This was reimplemented because the current version does not handle UNC paths properly, i.e. it should not return anything less than the root. In all other respects it is identical to the current implementation.

Also, this method will convert all forward slashes to backslashes.

Examples:

File.dirname("C:\\foo\\bar\\baz.txt") -> "C:\\foo\\bar"
File.dirname("\\\\foo\\bar")          -> "\\\\foo\\bar"
# File lib/win32/file.rb, line 105
def self.dirname(file)
  file = string_check(file)

  # Short circuit for empty paths
  return '.' if file.empty?

  # Store original encoding, restore it later
  encoding = file.encoding

  # Convert to UTF-16LE
  wfile = file.wincode

  # Return a root path as-is.
  if PathIsRootW(wfile)
    return file.tr(File::SEPARATOR, File::ALT_SEPARATOR)
  end

  ptr = FFI::MemoryPointer.from_string(wfile)

  # Remove trailing slashes if present
  while result = PathRemoveBackslashW(ptr)
    break unless result.empty?
  end

  # Remove trailing file name if present
  unless PathRemoveFileSpecW(ptr)
    raise SystemCallError.new("PathRemoveFileSpec", FFI.errno)
  end

  wfile = ptr.read_bytes(wfile.size * 2).split("\000\000").first

  # Empty paths, short relative paths
  if wfile.nil? or wfile.empty?
    return '.'
  end

  # Return to original encoding
  file = wfile.tr(0.chr, '').encode(encoding)

  ptr.free

  file
end
executable?(file) click to toggle source

Returns whether or not the file is executable.

# File lib/win32/file.rb, line 418
def self.executable?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).executable?
end
Also aliased as: executable_real?
executable_real?(file)
Alias for: executable?
file?(file) click to toggle source

Returns whether or not the file is a regular file.

# File lib/win32/file.rb, line 425
def self.file?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).file?
end
ftype(file) click to toggle source

Identifies the type of file. The return string is one of 'file', 'directory', 'characterSpecial', 'socket' or 'unknown'.

# File lib/win32/file.rb, line 433
def self.ftype(file)
  File::Stat.new(file).ftype
end
grpowned?(file) click to toggle source

Returns true if the process owner's ID is the same as one of the file's groups.

# File lib/win32/file.rb, line 439
def self.grpowned?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).grpowned?
end
join(*args) click to toggle source

Join path string components together into a single string.

This method was reimplemented so that it automatically converts forward slashes to backslashes. It is otherwise identical to the core File.join method.

Examples:

File.join("C:", "foo", "bar") # => C:\foo\bar
File.join("foo", "bar")       # => foo\bar
# File lib/win32/file.rb, line 160
def self.join(*args)
  return join_orig(*args).tr("/", "\\")
end
Also aliased as: join_orig
join_orig(*args)
Alias for: join
long_path(file) click to toggle source

Returns path in long format. For example, if 'SOMEFI~1.TXT' was the argument provided, and the short representation for 'somefile.txt', then this method would return 'somefile.txt'.

Note that certain file system optimizations may prevent this method from working as expected. In that case, you will get back the file name in 8.3 format.

# File lib/win32/file.rb, line 189
def self.long_path(file)
  buffer = FFI::Buffer.new(:wint_t, 1024, true)
  wfile  = string_check(file).wincode

  length = GetLongPathNameW(wfile, buffer, buffer.size)

  if length == 0 || length > buffer.size / 2
    raise SystemCallError.new('GetLongPathName', FFI.errno)
  end

  buffer.read_bytes(length * 2).wstrip
end
lstat(file)
Alias for: stat
mtime(file, time = nil) click to toggle source

Returns the file's creation time. If a time argument is provided, it sets the file's creation time. The time argument may be a Time object or a numeric value.

# File lib/win32/file.rb, line 448
def self.mtime(file, time = nil)
  set_filetime(file, nil, nil, time) if time
  File::Stat.new(file).mtime
end
owned?(file) click to toggle source

Returns whether or not the current process owner is the owner of the file.

# File lib/win32/file.rb, line 455
def self.owned?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).owned?
end
pipe?(file) click to toggle source

Returns whether or not the file is a pipe.

# File lib/win32/file.rb, line 462
def self.pipe?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).pipe?
end
Also aliased as: socket?
readable?(file) click to toggle source

Returns whether or not the file is readable by the process owner.

# File lib/win32/file.rb, line 469
def self.readable?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).readable?
end
readable_real?(file) click to toggle source

Synonym for File.readable?

# File lib/win32/file.rb, line 476
def self.readable_real?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).readable_real?
end
realdirpath(file, relative_to = nil) click to toggle source

Converts path to a full file path, with all symlinks resolved and relative paths made absolute. If a second parameter if present, it is used as the base for resolving leading relative path segments.

Unlike File.realpath, an error is not raised if the final path created using a relative path argument doesn't exist.

# File lib/win32/file.rb, line 283
def self.realdirpath(file, relative_to = nil)
  file = string_check(file)

  if symlink?(file)
    if relative_to
      File.join(relative_to, File.basename(readlink(file)))
    else
      readlink(file)
    end
  else
    realdirpath_orig(file, relative_to)
  end
end
Also aliased as: realdirpath_orig
realdirpath_orig(file, relative_to = nil)
Alias for: realdirpath
realpath(file, relative_to = nil) click to toggle source

Converts path to a full file path, with all symlinks resolved and relative paths made absolute. If a second parameter if present, it is used as the base for resolving leading relative path segments.

# File lib/win32/file.rb, line 303
def self.realpath(file, relative_to = nil)
  file = string_check(file)
  relative_to = string_check(relative_to) if relative_to

  if symlink?(file)
    if relative_to
      result = File.join(relative_to, File.basename(readlink(file)))
      if File.exist?(result)
        result
      else
        raise SystemCallError.new(result, 2) # Errno::ENOENT
      end
    else
      readlink(file)
    end
  else
    realpath_orig(file, relative_to)
  end
end
Also aliased as: realpath_orig
realpath_orig(file, relative_to = nil)
Alias for: realpath
short_path(file) click to toggle source

Returns path in 8.3 format. For example, 'c:documentation.doc' would be returned as 'c:docume~1.doc'.

# File lib/win32/file.rb, line 205
def self.short_path(file)
  buffer = FFI::Buffer.new(:wint_t, 1024, true)
  wfile  = string_check(file).wincode

  length = GetShortPathNameW(wfile, buffer, buffer.size)

  if length == 0 || length > buffer.size / 2
    raise SystemCallError.new('GetShortPathName', FFI.errno)
  end

  buffer.read_bytes(length * 2).wstrip
end
socket?(file)
Alias for: pipe?
split(file) click to toggle source

Splits the given string into a directory and a file component and returns them in a two element array. This was reimplemented because the current version does not handle UNC paths properly.

# File lib/win32/file.rb, line 168
def self.split(file)
  file = string_check(file)
  array = []

  if file.empty? || PathIsRootW(file.wincode)
    array.push(file, '')
  else
    array.push(File.dirname(file), File.basename(file))
  end

  array
end
stat(file) click to toggle source

Returns a File::Stat object as defined in the win32-file-stat library.

# File lib/win32/file.rb, line 483
def self.stat(file)
  File::Stat.new(file)
end
Also aliased as: lstat
world_readable?(file) click to toggle source

Returns whether or not the file is readable by others. Note that this merely returns true or false, not permission bits (or nil).

# File lib/win32/file.rb, line 490
def self.world_readable?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).world_readable?
end
world_writable?(file) click to toggle source

Returns whether or not the file is writable by others. Note that this merely returns true or false, not permission bits (or nil).

# File lib/win32/file.rb, line 498
def self.world_writable?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).world_writable?
end
writable?(file) click to toggle source

Returns whether or not the file is writable by the current process owner.

# File lib/win32/file.rb, line 505
def self.writable?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).writable?
end
writable_real?(file) click to toggle source

Synonym for File.writable?

# File lib/win32/file.rb, line 512
def self.writable_real?(file)
  return false unless File.exist?(file)
  File::Stat.new(file).writable_real?
end

Private Class Methods

set_filetime(path, ctime = nil, atime = nil, mtime = nil) click to toggle source

Internal method for setting the file time.

# File lib/win32/file.rb, line 544
def self.set_filetime(path, ctime = nil, atime = nil, mtime = nil)
  begin
    handle = CreateFileW(
      path.wincode,
      FILE_WRITE_ATTRIBUTES,
      FILE_SHARE_READ | FILE_SHARE_WRITE,
      nil,
      OPEN_EXISTING,
      FILE_ATTRIBUTE_NORMAL,
      0
    )

    if handle == INVALID_HANDLE_VALUE
      raise SystemCallError.new('CreateFile', FFI.errno)
    end

    ftimes = [] # 0 = ctime, 1 = atime, 2 = mtime

    [ctime, atime, mtime].each{ |time|
      if time.nil?
        ftimes << nil
        next
      else
        systime = SYSTEMTIME.new(time)
        ftime = FILETIME.new

        if SystemTimeToFileTime(systime, ftime)
          ftimes << ftime
        else
          raise SystemCallError.new('SystemTimetoFileTime', FFI.errno)
        end
      end
    }

    unless SetFileTime(handle, ftimes[0], ftimes[1], ftimes[2])
      raise SystemCallError.new('SetFileTime', FFI.errno)
    end
  ensure
    CloseHandle(handle) if handle
  end
end
string_check(arg) click to toggle source

Simulate Ruby's string checking

# File lib/win32/file.rb, line 536
def self.string_check(arg)
  return arg if arg.is_a?(String)
  return arg.send(:to_str) if arg.respond_to?(:to_str, true) # MRI allows private to_str
  return arg.to_path if arg.respond_to?(:to_path)
  raise TypeError
end

Public Instance Methods

stat() click to toggle source

Same as MRI, except it returns a stat object using the win32-file-stat gem.

# File lib/win32/file.rb, line 528
def stat
  File::Stat.new(self.path)
end