diff options
author | Seth Chisamore <schisamo@opscode.com> | 2011-11-18 16:11:23 -0500 |
---|---|---|
committer | Seth Chisamore <schisamo@opscode.com> | 2011-12-08 20:10:56 -0500 |
commit | 447604d5a06a149087d38725b3281e712e18e7db (patch) | |
tree | e09789ba0f61d3d55413853122d2dd82693c84a1 /chef | |
parent | 701f1aa0458b3353f14ea1dd86a6812592798f9f (diff) | |
download | chef-447604d5a06a149087d38725b3281e712e18e7db.tar.gz |
added readlink to Chef::Win32::File
Diffstat (limited to 'chef')
-rw-r--r-- | chef/lib/chef/win32/api/file.rb | 31 | ||||
-rw-r--r-- | chef/lib/chef/win32/file.rb | 41 |
2 files changed, 71 insertions, 1 deletions
diff --git a/chef/lib/chef/win32/api/file.rb b/chef/lib/chef/win32/api/file.rb index f0ef9fba49..5f1c5fc901 100644 --- a/chef/lib/chef/win32/api/file.rb +++ b/chef/lib/chef/win32/api/file.rb @@ -49,6 +49,13 @@ class Chef SYMBOLIC_LINK_FLAG_DIRECTORY = 0x1 + FILE_NAME_NORMALIZED = 0x0 + FILE_NAME_OPENED = 0x8 + + # TODO add the rest of these CONSTS + FILE_SHARE_READ = 0x00000001 + OPEN_EXISTING = 3 + =begin typedef struct _FILETIME { DWORD dwLowDateTime; @@ -101,6 +108,19 @@ typedef struct _WIN32_FIND_DATA { end =begin +HANDLE WINAPI CreateFile( + __in LPCTSTR lpFileName, + __in DWORD dwDesiredAccess, + __in DWORD dwShareMode, + __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes, + __in DWORD dwCreationDisposition, + __in DWORD dwFlagsAndAttributes, + __in_opt HANDLE hTemplateFile +); +=end + attach_function :CreateFileW, [:LPCTSTR, :DWORD, :DWORD, :LPSECURITY_ATTRIBUTES, :DWORD, :DWORD, :pointer], :HANDLE + +=begin BOOL WINAPI FindClose( __inout HANDLE hFindFile ); @@ -113,6 +133,17 @@ DWORD WINAPI GetFileAttributes( ); =end attach_function :GetFileAttributesW, [:LPCWSTR], :DWORD + +=begin +DWORD WINAPI GetFinalPathNameByHandle( + __in HANDLE hFile, + __out LPTSTR lpszFilePath, + __in DWORD cchFilePath, + __in DWORD dwFlags +); +=end + attach_function :GetFinalPathNameByHandleW, [:HANDLE, :LPTSTR, :DWORD, :DWORD], :DWORD + =begin HANDLE WINAPI FindFirstFile( __in LPCTSTR lpFileName, diff --git a/chef/lib/chef/win32/file.rb b/chef/lib/chef/win32/file.rb index 86f8505931..b330a6bc95 100644 --- a/chef/lib/chef/win32/file.rb +++ b/chef/lib/chef/win32/file.rb @@ -18,6 +18,7 @@ # require 'chef/win32/api/file' +require 'chef/win32/api/security' require 'chef/win32/error' require 'chef/win32/unicode' @@ -27,6 +28,7 @@ class Chef class << self include Chef::Win32::API::File + include Chef::Win32::API::Security # Creates a symbolic link called +new_name+ for the file or directory # +old_name+. @@ -79,6 +81,24 @@ class Chef is_symlink end + # Returns the path of the of the symbolic link referred to by +file+. + # + # Requires Windows Vista or later. On older versions of Windows it + # will raise a NotImplementedError, as per MRI. + # + def readlink(link_name) + # TODO do a check for GetFinalPathNameByHandleW and + # raise NotImplemented exception on older Windows + open_file(link_name) do |handle| + buffer = FFI::MemoryPointer.new(0.chr * MAX_PATH) + num_chars = GetFinalPathNameByHandleW(handle, buffer, buffer.size, FILE_NAME_NORMALIZED) + if num_chars == 0 + Chef::Win32::Error.raise! #could be misleading if problem is too small buffer size as GetLastError won't report failure + end + buffer.read_wstring(num_chars).sub(path_prepender, "") + end + end + private # takes the given path pre-pends "\\?\" and @@ -86,7 +106,11 @@ class Chef # to be passed to the *W vesion of WinAPI File # functions def encode_path(path) - ("\\\\?\\" << path).to_wstring + (path_prepender << path).to_wstring + end + + def path_prepender + "\\\\?\\" end # retrieves a file search handle and passes it @@ -106,6 +130,21 @@ class Chef end end + def open_file(path, &block) + begin + path = encode_path(path) + handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, + nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nil) + + if handle == INVALID_HANDLE_VALUE + Chef::Win32::Error.raise! + end + block.call(handle) + ensure + FindClose(handle) if handle && handle != INVALID_HANDLE_VALUE + end + end + end end |