class Fluent::WindowsFile

Constants

INVALID_HANDLE_VALUE

Attributes

io[R]

Public Class Methods

new(path, mode_enc='r') click to toggle source
# File lib/fluent/file_wrapper.rb, line 50
def initialize(path, mode_enc='r')
  @path = path
  mode, enc = mode_enc.split(":", 2)
  @io = File.open(path, mode2flags(mode))
  @io.set_encoding(enc) if enc
  @file_handle = Win32API._get_osfhandle(@io.to_i)
  @io.instance_variable_set(:@file_index, self.ino)
  def @io.ino
    @file_index
  end
end

Public Instance Methods

close() click to toggle source
# File lib/fluent/file_wrapper.rb, line 62
def close
  @io.close
  @file_handle = INVALID_HANDLE_VALUE
end
ino() click to toggle source

To keep backward compatibility, we continue to use GetFileInformationByHandle() to get file id. Note that Ruby’s File.stat uses GetFileInformationByHandleEx() with FileIdInfo and returned value is different with above one, former one is 64 bit while later one is 128bit.

# File lib/fluent/file_wrapper.rb, line 72
def ino
  by_handle_file_information = '\0'*(4+8+8+8+4+4+4+4+4+4)   #72bytes

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

  by_handle_file_information.unpack("I11Q1")[11] # fileindex
end
stat() click to toggle source
# File lib/fluent/file_wrapper.rb, line 82
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/file_wrapper.rb, line 124
def delete_pending
  file_standard_info = 0x01
  bufsize = 1024
  buf = '\0' * bufsize

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

  return buf.unpack("QQICC")[3] != 0
end
mode2flags(mode) click to toggle source
# File lib/fluent/file_wrapper.rb, line 92
def mode2flags(mode)
  # Always inject File::Constants::SHARE_DELETE
  # https://github.com/fluent/fluentd/pull/3585#issuecomment-1101502617
  # To enable SHARE_DELETE, BINARY is also required.
  # https://bugs.ruby-lang.org/issues/11218
  # https://github.com/ruby/ruby/blob/d6684f063bc53e3cab025bd39526eca3b480b5e7/win32/win32.c#L6332-L6345
  flags = BINARY | SHARE_DELETE
  case mode.delete("b")
  when "r"
    flags |= RDONLY
  when "r+"
    flags |= RDWR
  when "w"
    flags |= WRONLY | CREAT | TRUNC
  when "w+"
    flags |= RDWR | CREAT | TRUNC
  when "a"
    flags |= WRONLY | CREAT | APPEND
  when "a+"
    flags |= RDWR | CREAT | APPEND
  else
    raise Errno::EINVAL.new("Unsupported mode by Fluent::FileWrapper: #{mode}")
  end
end