From 77472a9cdf9dc9706911c1bbe85e04c0831c7fe9 Mon Sep 17 00:00:00 2001 From: Takuro Ashie Date: Thu, 1 Sep 2022 14:59:22 +0900 Subject: [PATCH] Define Fluent::FileWrapper at file_wrapper.rb even on non-Windows Signed-off-by: Takuro Ashie --- lib/fluent/file_wrapper.rb | 196 ++++++++++++++++++----------------- lib/fluent/plugin/in_tail.rb | 7 +- 2 files changed, 101 insertions(+), 102 deletions(-) diff --git a/lib/fluent/file_wrapper.rb b/lib/fluent/file_wrapper.rb index 91075a2aed..383862671f 100644 --- a/lib/fluent/file_wrapper.rb +++ b/lib/fluent/file_wrapper.rb @@ -14,118 +14,122 @@ # limitations under the License. # -require 'fluent/win32api' - -module Fluent - module FileWrapper - def self.open(path, mode='r') - io = WindowsFile.new(path, mode).io - if block_given? - v = yield io - io.close - v - else - io +unless Fluent.windows? + Fluent::FileWrapper = File +else + require 'fluent/win32api' + + module Fluent + module FileWrapper + def self.open(path, mode='r') + io = WindowsFile.new(path, mode).io + if block_given? + v = yield io + io.close + v + else + io + end end - end - def self.stat(path) - f = WindowsFile.new(path) - s = f.stat - f.close - s + def self.stat(path) + f = WindowsFile.new(path) + s = f.stat + f.close + s + end end - end - class WindowsFile - include File::Constants + class WindowsFile + include File::Constants - attr_reader :io + attr_reader :io - INVALID_HANDLE_VALUE = -1 + INVALID_HANDLE_VALUE = -1 - def initialize(path, mode='r') - @path = path - @io = File.open(path, mode2flags(mode)) - @file_handle = Win32API._get_osfhandle(@io.to_i) - @io.instance_variable_set(:@file_index, self.ino) - def @io.ino - @file_index + def initialize(path, mode='r') + @path = path + @io = File.open(path, mode2flags(mode)) + @file_handle = Win32API._get_osfhandle(@io.to_i) + @io.instance_variable_set(:@file_index, self.ino) + def @io.ino + @file_index + end end - end - - def close - @io.close - @file_handle = INVALID_HANDLE_VALUE - end - - # 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. - 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 + def close + @io.close + @file_handle = INVALID_HANDLE_VALUE end - by_handle_file_information.unpack("I11Q1")[11] # fileindex - end + # 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. + def ino + by_handle_file_information = '\0'*(4+8+8+8+4+4+4+4+4+4) #72bytes - 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 + unless Win32API.GetFileInformationByHandle(@file_handle, by_handle_file_information) + return 0 + end - private - - 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}") + by_handle_file_information.unpack("I11Q1")[11] # fileindex end - end - # 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(). - # - # https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex - # - def delete_pending - file_standard_info = 0x01 - bufsize = 1024 - buf = '\0' * bufsize - - unless Win32API.GetFileInformationByHandleEx(@file_handle, file_standard_info, buf, bufsize) - return false + 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 - return buf.unpack("QQICC")[3] != 0 + private + + 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 + + # 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(). + # + # https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getfileinformationbyhandleex + # + 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 end end -end if Fluent.windows? +end diff --git a/lib/fluent/plugin/in_tail.rb b/lib/fluent/plugin/in_tail.rb index 5346994b31..fb29dd249f 100644 --- a/lib/fluent/plugin/in_tail.rb +++ b/lib/fluent/plugin/in_tail.rb @@ -25,12 +25,7 @@ require 'fluent/capability' require 'fluent/plugin/in_tail/position_file' require 'fluent/plugin/in_tail/group_watch' - -if Fluent.windows? - require 'fluent/file_wrapper' -else - Fluent::FileWrapper = File -end +require 'fluent/file_wrapper' module Fluent::Plugin class TailInput < Fluent::Plugin::Input