Module: Puppet::Util::Windows::File
- Extended by:
- FFI::Library, String
- Defined in:
- lib/puppet/util/windows.rb,
lib/puppet/util/windows/file.rb
Defined Under Namespace
Classes: REPARSE_DATA_BUFFER
Constant Summary collapse
- FILE_ATTRIBUTE_READONLY =
0x00000001
- SYNCHRONIZE =
0x100000
- STANDARD_RIGHTS_REQUIRED =
0xf0000
- STANDARD_RIGHTS_READ =
0x20000
- STANDARD_RIGHTS_WRITE =
0x20000
- STANDARD_RIGHTS_EXECUTE =
0x20000
- STANDARD_RIGHTS_ALL =
0x1F0000
- SPECIFIC_RIGHTS_ALL =
0xFFFF
- FILE_READ_DATA =
1
- FILE_WRITE_DATA =
2
- FILE_APPEND_DATA =
4
- FILE_READ_EA =
8
- FILE_WRITE_EA =
16
- FILE_EXECUTE =
32
- FILE_DELETE_CHILD =
64
- FILE_READ_ATTRIBUTES =
128
- FILE_WRITE_ATTRIBUTES =
256
- FILE_ALL_ACCESS =
STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1FF
- FILE_GENERIC_READ =
STANDARD_RIGHTS_READ | FILE_READ_DATA | FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE
- FILE_GENERIC_WRITE =
STANDARD_RIGHTS_WRITE | FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA | SYNCHRONIZE
- FILE_GENERIC_EXECUTE =
STANDARD_RIGHTS_EXECUTE | FILE_READ_ATTRIBUTES | FILE_EXECUTE | SYNCHRONIZE
- REPLACEFILE_WRITE_THROUGH =
0x1
- REPLACEFILE_IGNORE_MERGE_ERRORS =
0x2
- REPLACEFILE_IGNORE_ACL_ERRORS =
0x3
- INVALID_FILE_ATTRIBUTES =
define INVALID_FILE_ATTRIBUTES (DWORD (-1))
0xFFFFFFFF
- INVALID_HANDLE_VALUE =
define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
FFI::Pointer.new(-1).address
- FILE_ATTRIBUTE_REPARSE_POINT =
0x400
- GENERIC_READ =
0x80000000
- GENERIC_WRITE =
0x40000000
- GENERIC_EXECUTE =
0x20000000
- GENERIC_ALL =
0x10000000
- FILE_SHARE_READ =
1
- FILE_SHARE_WRITE =
2
- OPEN_EXISTING =
3
- FILE_FLAG_OPEN_REPARSE_POINT =
0x00200000
- FILE_FLAG_BACKUP_SEMANTICS =
0x02000000
- ERROR_FILE_NOT_FOUND =
2
- ERROR_PATH_NOT_FOUND =
3
Class Method Summary collapse
- .add_attributes(path, flags) ⇒ Object
- .create_file(file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file_handle) ⇒ Object
- .device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil) ⇒ Object
- .exist?(path) ⇒ Boolean
- .get_attributes(file_name, raise_on_invalid = true) ⇒ Object
- .get_long_pathname(path) ⇒ Object
- .get_reparse_point_data(handle, &block) ⇒ Object
- .get_short_pathname(path) ⇒ Object
- .lstat(file_name) ⇒ Object
- .move_file_ex(source, target, flags = 0) ⇒ Object
- .open_symlink(link_name) ⇒ Object
- .readlink(link_name) ⇒ Object
- .remove_attributes(path, flags) ⇒ Object
- .replace_file(target, source) ⇒ Object
- .set_attributes(path, flags) ⇒ Object
- .stat(file_name) ⇒ Object
- .symlink(target, symlink) ⇒ Object
- .symlink?(file_name) ⇒ Boolean
Methods included from FFI::Library
Methods included from String
Class Method Details
.add_attributes(path, flags) ⇒ Object
138 139 140 141 142 143 144 |
# File 'lib/puppet/util/windows/file.rb', line 138 def add_attributes(path, flags) oldattrs = get_attributes(path) if (oldattrs | flags) != oldattrs set_attributes(path, oldattrs | flags) end end |
.create_file(file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file_handle) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 |
# File 'lib/puppet/util/windows/file.rb', line 166 def self.create_file(file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file_handle) result = CreateFileW(wide_string(file_name.to_s), desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file_handle) return result unless result == INVALID_HANDLE_VALUE raise Puppet::Util::Windows::Error.new( "CreateFile(#{file_name}, #{desired_access.to_s(8)}, #{share_mode.to_s(8)}, " + "#{security_attributes}, #{creation_disposition.to_s(8)}, " + "#{flags_and_attributes.to_s(8)}, #{template_file_handle})") end |
.device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil) ⇒ Object
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/puppet/util/windows/file.rb', line 191 def self.device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil) if out_buffer.nil? raise Puppet::Util::Windows::Error.new(_("out_buffer is required")) end FFI::MemoryPointer.new(:dword, 1) do |bytes_returned_ptr| result = DeviceIoControl( handle, io_control_code, in_buffer, in_buffer.nil? ? 0 : in_buffer.size, out_buffer, out_buffer.size, bytes_returned_ptr, nil ) if result == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new( "DeviceIoControl(#{handle}, #{io_control_code}, " + "#{in_buffer}, #{in_buffer ? in_buffer.size : ''}, " + "#{out_buffer}, #{out_buffer ? out_buffer.size : ''}") end end out_buffer end |
.exist?(path) ⇒ Boolean
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/puppet/util/windows/file.rb', line 97 def exist?(path) path = path.to_str if path.respond_to?(:to_str) # support WatchedFile path = path.to_s # support String and Pathname seen_paths = [] # follow up to 64 symlinks before giving up 0.upto(64) do |depth| # return false if this path has been seen before. This is protection against circular symlinks return false if seen_paths.include?(path.downcase) result = get_attributes(path,false) # return false for path not found return false if result == INVALID_FILE_ATTRIBUTES # return true if path exists and it's not a symlink # Other file attributes are ignored. https://msdn.microsoft.com/en-us/library/windows/desktop/gg258117(v=vs.85).aspx return true if (result & FILE_ATTRIBUTE_REPARSE_POINT) != FILE_ATTRIBUTE_REPARSE_POINT # walk the symlink and try again... seen_paths << path.downcase path = readlink(path) end false end |
.get_attributes(file_name, raise_on_invalid = true) ⇒ Object
128 129 130 131 132 133 134 135 |
# File 'lib/puppet/util/windows/file.rb', line 128 def get_attributes(file_name, raise_on_invalid = true) result = GetFileAttributesW(wide_string(file_name.to_s)) if raise_on_invalid && result == INVALID_FILE_ATTRIBUTES raise Puppet::Util::Windows::Error.new("GetFileAttributes(#{file_name})") end result end |
.get_long_pathname(path) ⇒ Object
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 |
# File 'lib/puppet/util/windows/file.rb', line 267 def get_long_pathname(path) converted = '' FFI::Pointer.from_string_to_wide_string(path) do |path_ptr| # includes terminating NULL buffer_size = GetLongPathNameW(path_ptr, FFI::Pointer::NULL, 0) FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr| if GetLongPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new(_("Failed to call GetLongPathName")) end converted = converted_ptr.read_wide_string(buffer_size - 1) end end converted end |
.get_reparse_point_data(handle, &block) ⇒ Object
180 181 182 183 184 185 186 187 188 189 |
# File 'lib/puppet/util/windows/file.rb', line 180 def self.get_reparse_point_data(handle, &block) # must be multiple of 1024, min 10240 FFI::MemoryPointer.new(REPARSE_DATA_BUFFER.size) do |reparse_data_buffer_ptr| device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr) yield REPARSE_DATA_BUFFER.new(reparse_data_buffer_ptr) end # underlying struct MemoryPointer has been cleaned up by this point, nothing to return nil end |
.get_short_pathname(path) ⇒ Object
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 |
# File 'lib/puppet/util/windows/file.rb', line 285 def get_short_pathname(path) converted = '' FFI::Pointer.from_string_to_wide_string(path) do |path_ptr| # includes terminating NULL buffer_size = GetShortPathNameW(path_ptr, FFI::Pointer::NULL, 0) FFI::MemoryPointer.new(:wchar, buffer_size) do |converted_ptr| if GetShortPathNameW(path_ptr, converted_ptr, buffer_size) == FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new("Failed to call GetShortPathName") end converted = converted_ptr.read_wide_string(buffer_size - 1) end end converted end |
.lstat(file_name) ⇒ Object
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 |
# File 'lib/puppet/util/windows/file.rb', line 327 def lstat(file_name) file_name = file_name.to_s # accommodate PathName or String # monkey'ing around! stat = File.lstat(file_name) singleton_class = class << stat; self; end singleton_class.send(:define_method, :mode) do Puppet::Util::Windows::Security.get_mode(file_name) end if symlink?(file_name) def stat.ftype "link" end end stat end |
.move_file_ex(source, target, flags = 0) ⇒ Object
75 76 77 78 79 80 81 82 83 |
# File 'lib/puppet/util/windows/file.rb', line 75 def move_file_ex(source, target, flags = 0) result = MoveFileExW(wide_string(source.to_s), wide_string(target.to_s), flags) return true if result != FFI::WIN32_FALSE raise Puppet::Util::Windows::Error. new("MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})") end |
.open_symlink(link_name) ⇒ Object
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/puppet/util/windows/file.rb', line 236 def self.open_symlink(link_name) begin yield handle = create_file( link_name, GENERIC_READ, FILE_SHARE_READ, nil, # security_attributes OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0) # template_file ensure FFI::WIN32.CloseHandle(handle) if handle end # handle has had CloseHandle called against it, so nothing to return nil end |
.readlink(link_name) ⇒ Object
254 255 256 257 258 259 260 261 |
# File 'lib/puppet/util/windows/file.rb', line 254 def readlink(link_name) link = nil open_symlink(link_name) do |handle| link = resolve_symlink(handle) end link end |
.remove_attributes(path, flags) ⇒ Object
147 148 149 150 151 152 153 |
# File 'lib/puppet/util/windows/file.rb', line 147 def remove_attributes(path, flags) oldattrs = get_attributes(path) if (oldattrs & ~flags) != oldattrs set_attributes(path, oldattrs & ~flags) end end |
.replace_file(target, source) ⇒ Object
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/puppet/util/windows/file.rb', line 55 def replace_file(target, source) target_encoded = wide_string(target.to_s) source_encoded = wide_string(source.to_s) flags = REPLACEFILE_IGNORE_MERGE_ERRORS backup_file = nil result = ReplaceFileW( target_encoded, source_encoded, backup_file, flags, FFI::Pointer::NULL, FFI::Pointer::NULL ) return true if result != FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new("ReplaceFile(#{target}, #{source})") end |
.set_attributes(path, flags) ⇒ Object
156 157 158 159 160 161 |
# File 'lib/puppet/util/windows/file.rb', line 156 def set_attributes(path, flags) success = SetFileAttributesW(wide_string(path), flags) != FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new(_("Failed to set file attributes")) if !success success end |
.stat(file_name) ⇒ Object
303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 |
# File 'lib/puppet/util/windows/file.rb', line 303 def stat(file_name) file_name = file_name.to_s # accommodate PathName or String stat = File.stat(file_name) singleton_class = class << stat; self; end target_path = file_name if symlink?(file_name) target_path = readlink(file_name) link_ftype = File.stat(target_path).ftype # sigh, monkey patch instance method for instance, and close over link_ftype singleton_class.send(:define_method, :ftype) do link_ftype end end singleton_class.send(:define_method, :mode) do Puppet::Util::Windows::Security.get_mode(target_path) end stat end |
.symlink(target, symlink) ⇒ Object
86 87 88 89 90 91 92 93 |
# File 'lib/puppet/util/windows/file.rb', line 86 def symlink(target, symlink) flags = File.directory?(target) ? 0x1 : 0x0 result = CreateSymbolicLinkW(wide_string(symlink.to_s), wide_string(target.to_s), flags) return true if result != FFI::WIN32_FALSE raise Puppet::Util::Windows::Error.new( "CreateSymbolicLink(#{symlink}, #{target}, #{flags.to_s(8)})") end |
.symlink?(file_name) ⇒ Boolean
218 219 220 221 222 223 |
# File 'lib/puppet/util/windows/file.rb', line 218 def symlink?(file_name) attributes = get_attributes(file_name, false) return false if (attributes == INVALID_FILE_ATTRIBUTES) (attributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT end |