FFI symlink detection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ffi' | |
FILE_ATTRIBUTE_REPARSE_POINT = 0x400 | |
IO_REPARSE_TAG_SYMLINK = 0xA000000C | |
INVALID_FILE_ATTRIBUTES = 0xFFFFFFFF | |
INVALID_HANDLE_VALUE = 0xFFFFFFFF # -1 is also valid | |
module Win_Test | |
extend FFI::Library | |
MAX_PATH = 260 | |
class FILETIME < FFI::Struct | |
layout :dw_low_date_time, :uint32, | |
:dw_high_date_time, :uint32, | |
end | |
class WIN32_FIND_DATA < FFI::Struct | |
layout :dw_file_attributes, :uint32, | |
:ft_creation_time, FILETIME, | |
:ft_last_access_time, FILETIME, | |
:ft_last_write_time, FILETIME, | |
:n_file_size_high, :uint32, | |
:n_file_size_low, :uint32, | |
:dw_reserved_0, :uint32, | |
:dw_reserved_1, :uint32, | |
:c_file_name, [:char, MAX_PATH], | |
:c_alternate_file_name, [:char, 14], | |
end | |
ffi_lib 'kernel32' | |
ffi_convention :stdcall | |
=begin | |
DWORD WINAPI GetFileAttributes( | |
__in LPCTSTR lpFileName | |
); | |
=end | |
attach_function :get_file_attribute, :GetFileAttributesW, [:pointer], :uint32 | |
# FindFirstFileW returns a pointer - but the part that matters is the | |
# address it points to, not the value it contains, so declair as ulong | |
# to do comparisons against it | |
attach_function :find_first_file, :FindFirstFileW, [:pointer, :pointer], :ulong | |
attach_function :get_last_error, :GetLastError, [], :uint | |
end | |
#path = 'testfile.txt' | |
path = 'newtestfile.txt' | |
#puts path.encoding.name | |
#path = path.encode('UTF-16LE') | |
#puts path.encoding.name | |
value = Win_Test.get_file_attribute(path.encode('UTF-16LE')) | |
puts value | |
if (value == INVALID_FILE_ATTRIBUTES) | |
#this prints invalid at random times, depending on what I modify in the file | |
#can even be code I change below! | |
puts "Invalid" | |
#puts Win_Test.get_last_error | |
end | |
#puts value | |
if ((value & FILE_ATTRIBUTE_REPARSE_POINT) != 0) | |
puts "worked" | |
data = Win_Test::WIN32_FIND_DATA.new | |
handle = Win_Test.find_first_file(path, data) | |
# do I have to worry about closing the handle? | |
if handle == INVALID_HANDLE_VALUE | |
#puts handle | |
puts "Invalid Handle" | |
end | |
#puts handle | |
#puts data | |
#puts data[:dw_file_attributes] | |
#puts data[:dw_reserved_0] | |
if data[:dw_reserved_0] == IO_REPARSE_TAG_SYMLINK | |
puts "Symlink" | |
else | |
puts "Not symlink" | |
end | |
# do I have to worry about closing the handle? | |
# does FFI take care of that? | |
else | |
puts "failed" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment