diff options
Diffstat (limited to 'lib/chef/win32/file.rb')
-rw-r--r-- | lib/chef/win32/file.rb | 53 |
1 files changed, 28 insertions, 25 deletions
diff --git a/lib/chef/win32/file.rb b/lib/chef/win32/file.rb index 1009f8c5a9..55fc2461e8 100644 --- a/lib/chef/win32/file.rb +++ b/lib/chef/win32/file.rb @@ -1,7 +1,7 @@ # # Author:: Seth Chisamore (<schisamo@chef.io>) -# Author:: Mark Mzyk (<mmzyk@ospcode.com>) -# Copyright:: Copyright 2011-2016, Chef Software Inc. +# Author:: Mark Mzyk (<mmzyk@chef.io>) +# Copyright:: Copyright (c) Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -17,11 +17,12 @@ # limitations under the License. # -require "chef/mixin/wide_string" -require "chef/win32/api/file" -require "chef/win32/api/security" -require "chef/win32/error" -require "chef/win32/unicode" +require_relative "../mixin/wide_string" +require_relative "api/file" +require_relative "api/security" +require_relative "error" +require_relative "unicode" +require_relative "version" class Chef module ReservedNames::Win32 @@ -40,6 +41,7 @@ class Chef # def self.link(old_name, new_name) raise Errno::ENOENT, "(#{old_name}, #{new_name})" unless ::File.exist?(old_name) || ::File.symlink?(old_name) + # TODO do a check for CreateHardLinkW and # raise NotImplemented exception on older Windows old_name = encode_path(old_name) @@ -60,6 +62,7 @@ class Chef # TODO do a check for CreateSymbolicLinkW and # raise NotImplemented exception on older Windows flags = ::File.directory?(old_name) ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0 + flags |= SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE if Chef::ReservedNames::Win32::Version.new.win_10_creators_or_higher? old_name = encode_path(old_name) new_name = encode_path(new_name) unless CreateSymbolicLinkW(new_name, old_name, flags) @@ -75,7 +78,7 @@ class Chef def self.symlink?(file_name) is_symlink = false path = encode_path(file_name) - if ::File.exists?(file_name) || ::File.symlink?(file_name) + if ::File.exist?(file_name) || ::File.symlink?(file_name) if (GetFileAttributesW(path) & FILE_ATTRIBUTE_REPARSE_POINT) > 0 file_search_handle(file_name) do |handle, find_data| if find_data[:dw_reserved_0] == IO_REPARSE_TAG_SYMLINK @@ -87,13 +90,22 @@ class Chef is_symlink end + def self.realpath(file_name) + if symlink?(file_name) + readlink(file_name) + else + file_name + end + 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 self.readlink(link_name) - raise Errno::ENOENT, link_name unless ::File.exists?(link_name) || ::File.symlink?(link_name) + raise Errno::ENOENT, link_name unless ::File.exist?(link_name) || ::File.symlink?(link_name) + symlink_file_handle(link_name) do |handle| # Go to DeviceIoControl to get the symlink information # http://msdn.microsoft.com/en-us/library/windows/desktop/aa364571(v=vs.85).aspx @@ -111,8 +123,8 @@ class Chef # Return the link destination (strip off \??\ at the beginning, which is a local filesystem thing) link_dest = reparse_buffer.reparse_buffer.substitute_name - if link_dest =~ /^\\\?\?\\/ - link_dest = link_dest[4..-1] + if /^\\\?\?\\/.match?(link_dest) + link_dest = link_dest[4..] end link_dest end @@ -154,16 +166,6 @@ class Chef VersionInfo.new(file_name) end - def self.verify_links_supported! - begin - CreateSymbolicLinkW(nil) - rescue Chef::Exceptions::Win32APIFunctionNotImplemented => e - raise e - rescue Exception - # things are ok. - end - end - def self.file_access_check(path, desired_access) security_descriptor = Chef::ReservedNames::Win32::Security.get_file_security(path) token_rights = Chef::ReservedNames::Win32::Security::TOKEN_IMPERSONATE | @@ -172,7 +174,8 @@ class Chef Chef::ReservedNames::Win32::Security::STANDARD_RIGHTS_READ token = Chef::ReservedNames::Win32::Security.open_process_token( Chef::ReservedNames::Win32::Process.get_current_process, - token_rights) + token_rights + ) duplicate_token = token.duplicate_token(:SecurityImpersonation) mapping = Chef::ReservedNames::Win32::Security::GENERIC_MAPPING.new @@ -182,7 +185,7 @@ class Chef mapping[:GenericAll] = Chef::ReservedNames::Win32::Security::FILE_ALL_ACCESS Chef::ReservedNames::Win32::Security.access_check(security_descriptor, duplicate_token, - desired_access, mapping) + desired_access, mapping) end def self.delete_volume_mount_point(mount_point) @@ -214,5 +217,5 @@ class Chef end end -require "chef/win32/file/info" -require "chef/win32/file/version_info" +require_relative "file/info" +require_relative "file/version_info" |