From af20f1f996b58bef6972da92e3226135318c60cd Mon Sep 17 00:00:00 2001 From: Serdar Sutay Date: Thu, 11 Dec 2014 16:43:46 -0800 Subject: As https://github.com/opscode/chef/issues/2580 summarizes, Link resource need to support relative paths in its 'to' attribute since one can create a symlink pointing to a relative location. This is useful if the directory that symlink resides in moves to a different place (e.g. mounting a disk on a separate location). This commit preserves relative paths inside the "encode_path" method used by the link operations and expands relative paths in similar fashion when being used by file operations. --- lib/chef/win32/api/file.rb | 16 +++++++++++++--- spec/functional/resource/link_spec.rb | 8 ++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/lib/chef/win32/api/file.rb b/lib/chef/win32/api/file.rb index 7a8dafd8b5..86b2b942c2 100644 --- a/lib/chef/win32/api/file.rb +++ b/lib/chef/win32/api/file.rb @@ -457,11 +457,21 @@ BOOL WINAPI DeviceIoControl( # takes the given path pre-pends "\\?\" and # UTF-16LE encodes it. Used to prepare paths # to be passed to the *W vesion of WinAPI File - # functions + # functions. + # This function is used by the "Link" resources where we need + # preserve relative paths because symbolic links can actually + # point to a relative path (relative to the link itself). def encode_path(path) (path_prepender << path.gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR)).to_wstring end + # Expands the path, prepends "\\?\" and UTF-16LE encodes it. + # This function is used by the "File" resources where we need + # convert relative paths to fully qualified paths. + def canonical_encode_path(path) + Chef::Util::PathHelper.canonical_path(path).to_wstring + end + def path_prepender "\\\\?\\" end @@ -478,7 +488,7 @@ BOOL WINAPI DeviceIoControl( # broader fix to map all the paths starting with "/" to # SYSTEM_DRIVE on windows. path = ::File.expand_path(path) if path.start_with? "/" - path = encode_path(path) + path = canonical_encode_path(path) find_data = WIN32_FIND_DATA.new handle = FindFirstFileW(path, find_data) if handle == INVALID_HANDLE_VALUE @@ -495,7 +505,7 @@ BOOL WINAPI DeviceIoControl( # ensures the handle is closed on exit of the block def file_handle(path, &block) begin - path = encode_path(path) + path = canonical_encode_path(path) handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, nil) diff --git a/spec/functional/resource/link_spec.rb b/spec/functional/resource/link_spec.rb index 209002b400..d39a0c2ef6 100644 --- a/spec/functional/resource/link_spec.rb +++ b/spec/functional/resource/link_spec.rb @@ -393,7 +393,7 @@ describe Chef::Resource::Link do File.open(@other_target, "w") { |file| file.write("eek") } symlink(@other_target, to) expect(symlink?(to)).to be_truthy - expect(readlink(target_file)).to eq(canonicalize(@other_target)) + expect(readlink(to)).to eq(canonicalize(@other_target)) end after(:each) do File.delete(@other_target) @@ -408,7 +408,7 @@ describe Chef::Resource::Link do @other_target = File.join(test_file_dir, make_tmpname("other_spec")) symlink(@other_target, to) expect(symlink?(to)).to be_truthy - expect(readlink(target_file)).to eq(canonicalize(@other_target)) + expect(readlink(to)).to eq(canonicalize(@other_target)) end context 'and the link does not yet exist' do include_context 'create symbolic link succeeds' @@ -552,7 +552,7 @@ describe Chef::Resource::Link do File.open(@other_target, "w") { |file| file.write("eek") } symlink(@other_target, to) expect(symlink?(to)).to be_truthy - expect(readlink(target_file)).to eq(canonicalize(@other_target)) + expect(readlink(to)).to eq(canonicalize(@other_target)) end after(:each) do File.delete(@other_target) @@ -574,7 +574,7 @@ describe Chef::Resource::Link do @other_target = File.join(test_file_dir, make_tmpname("other_spec")) symlink(@other_target, to) expect(symlink?(to)).to be_truthy - expect(readlink(target_file)).to eq(canonicalize(@other_target)) + expect(readlink(to)).to eq(canonicalize(@other_target)) end context 'and the link does not yet exist' do it 'links to the target file' do -- cgit v1.2.1