class Fluent::WindowsFile

To open and get stat with setting FILE_SHARE_DELETE

Public Class Methods

new(path, mode='r', sharemode=FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE) click to toggle source
# File lib/fluent/plugin/file_wrapper.rb, line 103
def initialize(path, mode='r', sharemode=FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE)
  @path = path
  @file_handle = INVALID_HANDLE_VALUE
  @mode = mode


  access, creationdisposition, seektoend = case mode.delete('b')
  when "r" ; [FILE_GENERIC_READ                     , OPEN_EXISTING, false]
  when "r+"; [FILE_GENERIC_READ | FILE_GENERIC_WRITE, OPEN_ALWAYS  , false]
  when "w" ; [FILE_GENERIC_WRITE                    , CREATE_ALWAYS, false]
  when "w+"; [FILE_GENERIC_READ | FILE_GENERIC_WRITE, CREATE_ALWAYS, false]
  when "a" ; [FILE_GENERIC_WRITE                    , OPEN_ALWAYS  , true]
  when "a+"; [FILE_GENERIC_READ | FILE_GENERIC_WRITE, OPEN_ALWAYS  , true]
  else raise "unknown mode '#{mode}'"
  end

  @file_handle = CreateFile.call(@path, access, sharemode,
                 0, creationdisposition, FILE_ATTRIBUTE_NORMAL, 0)
  if @file_handle == INVALID_HANDLE_VALUE
    win32err = Win32Error.new(Win32::API.last_error, path)
    errno = ServerEngine::RbWinSock.rb_w32_map_errno(win32err.errcode)
    if errno == Errno::EINVAL::Errno || win32err.wsaerr?
      # maybe failed to map
      raise win32err
    else
      raise SystemCallError.new(win32err.message, errno)
    end
  end
end

Public Instance Methods

close() click to toggle source
# File lib/fluent/plugin/file_wrapper.rb, line 133
def close
  CloseHandle.call(@file_handle)
  @file_handle = INVALID_HANDLE_VALUE
end
ino() click to toggle source
# File lib/fluent/plugin/file_wrapper.rb, line 148
def ino
  by_handle_file_information = '\0'*(4+8+8+8+4+4+4+4+4+4)   #72bytes

  unless GetFileInformationByHandle.call(@file_handle, by_handle_file_information)
    return 0
  end

  by_handle_file_information.unpack("I11Q1")[11] # fileindex
end
io() click to toggle source
# File lib/fluent/plugin/file_wrapper.rb, line 138
def io
  fd = _open_osfhandle(@file_handle, 0)
  raise Errno::ENOENT if fd == -1
  io = File.for_fd(fd, @mode)
  io.instance_variable_set :@ino, self.ino
  io.instance_variable_set :@path, @path
  io.extend WindowsFileExtension
  io
end
stat() click to toggle source
# File lib/fluent/plugin/file_wrapper.rb, line 179
def stat
  raise Errno::ENOENT if delete_pending
  s = File.stat(@path)
  s.instance_variable_set :@ino, self.ino
  def s.ino; @ino; end
  s
end

Private Instance Methods

delete_pending() click to toggle source

DeletePending is a Windows-specific file state that roughly means “this file is queued for deletion, so close any open handlers”

This flag can be retrieved via GetFileInformationByHandleEx().

docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex

# File lib/fluent/plugin/file_wrapper.rb, line 165
def delete_pending
  file_standard_info = 0x01
  bufsize = 1024
  buf = '\0' * bufsize

  unless GetFileInformationByHandleEx.call(@file_handle, file_standard_info, buf, bufsize)
    return false
  end

  return buf.unpack("QQICC")[3] != 0
end