Skip to content

Commit ba55d4b

Browse files
committed
WindowsFile: Fix incorrect error message
It passes win32 error codes to SystemCallError so that it doesn't show correct message for them. For example when ERROR_SHARING_VIOLATION(32) of win32 occurs, it shows Errno::EPIPE(32). Signed-off-by: Takuro Ashie <[email protected]>
1 parent 4b1ee63 commit ba55d4b

File tree

2 files changed

+105
-1
lines changed

2 files changed

+105
-1
lines changed

lib/fluent/plugin/file_wrapper.rb

+28-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,33 @@ def s.ino; @ino; end
4646
end
4747
end
4848

49+
class Win32Error < StandardError
50+
require 'windows/error'
51+
include Windows::Error
52+
53+
attr_reader :errcode
54+
55+
def initialize(errcode)
56+
@errcode = errcode
57+
end
58+
59+
def format_english_message(errcode)
60+
buf = 0.chr * 260
61+
flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY
62+
english_lang_id = 1033 # The result of MAKELANDID(LANG_ENGLISH, SUBLANG_ENGLISH_US)
63+
FormatMessageA.call(flags, 0, errcode, english_lang_id, buf, buf.size, 0)
64+
buf.force_encoding(Encoding.default_external).strip
65+
end
66+
67+
def message
68+
"code: #{@errcode}, #{format_english_message(@errcode)}"
69+
end
70+
71+
def ==(other)
72+
@errcode == other.errcode
73+
end
74+
end
75+
4976
# To open and get stat with setting FILE_SHARE_DELETE
5077
class WindowsFile
5178
require 'windows/file'
@@ -81,7 +108,7 @@ def initialize(path, mode='r', sharemode=FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_S
81108
if err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND || err == ERROR_ACCESS_DENIED
82109
raise SystemCallError.new(2)
83110
end
84-
raise SystemCallError.new(err)
111+
raise Win32Error.new(err)
85112
end
86113
end
87114

test/plugin/test_file_wrapper.rb

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
require_relative '../helper'
2+
require 'fluent/plugin/file_wrapper'
3+
4+
class FileWrapperTest < Test::Unit::TestCase
5+
require 'windows/file'
6+
include Windows::File
7+
8+
TMP_DIR = File.dirname(__FILE__) + "/../tmp/file_wrapper#{ENV['TEST_ENV_NUMBER']}"
9+
10+
def setup
11+
FileUtils.mkdir_p(TMP_DIR)
12+
end
13+
14+
def teardown
15+
FileUtils.rm_rf(TMP_DIR)
16+
end
17+
18+
sub_test_case 'Win32Error' do
19+
test 'equal' do
20+
assert_equal(Fluent::Win32Error.new(32),
21+
Fluent::Win32Error.new(32))
22+
end
23+
24+
test 'not equal' do
25+
assert_not_equal(Fluent::Win32Error.new(2),
26+
Fluent::Win32Error.new(32))
27+
end
28+
29+
test 'ERROR_SHARING_VIOLATION message' do
30+
assert_equal(Fluent::Win32Error.new(32).message.chomp,
31+
"code: 32, The process cannot access the file because it is being used by another process.")
32+
end
33+
end
34+
35+
sub_test_case 'WindowsFile exceptions' do
36+
test 'nothing raised' do
37+
begin
38+
path = "#{TMP_DIR}/test_windows_file.txt"
39+
file1 = file2 = nil
40+
file1 = File.open(path, "wb") do |f|
41+
end
42+
assert_nothing_raised do
43+
file2 = Fluent::WindowsFile.new(path)
44+
ensure
45+
file2.close
46+
end
47+
ensure
48+
file1.close if file1
49+
end
50+
end
51+
52+
test 'Errno::ENOENT raised' do
53+
path = "#{TMP_DIR}/nofile.txt"
54+
file = nil
55+
assert_raise(SystemCallError.new(2)) do
56+
file = Fluent::WindowsFile.new(path)
57+
ensure
58+
file.close if file
59+
end
60+
end
61+
62+
test 'ERROR_SHARING_VIOLATION raised' do
63+
begin
64+
path = "#{TMP_DIR}/test_windows_file.txt"
65+
file1 = file2 = nil
66+
file1 = File.open(path, "wb")
67+
assert_raise(Fluent::Win32Error.new(32)) do
68+
file2 = Fluent::WindowsFile.new(path, 'r', FILE_SHARE_READ)
69+
ensure
70+
file2.close if file2
71+
end
72+
ensure
73+
file1.close if file1
74+
end
75+
end
76+
end
77+
end if Fluent.windows?

0 commit comments

Comments
 (0)