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
- 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
134 135 136 137 138 139 140 |
# File 'lib/puppet/util/windows/file.rb', line 134 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
162 163 164 165 166 167 168 169 170 171 172 173 174 |
# File 'lib/puppet/util/windows/file.rb', line 162 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
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/puppet/util/windows/file.rb', line 187 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
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/puppet/util/windows/file.rb', line 93 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
124 125 126 127 128 129 130 131 |
# File 'lib/puppet/util/windows/file.rb', line 124 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
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/puppet/util/windows/file.rb', line 263 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
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/puppet/util/windows/file.rb', line 176 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
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/puppet/util/windows/file.rb', line 281 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
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'lib/puppet/util/windows/file.rb', line 323 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
71 72 73 74 75 76 77 78 79 |
# File 'lib/puppet/util/windows/file.rb', line 71 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
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 |
# File 'lib/puppet/util/windows/file.rb', line 232 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
250 251 252 253 254 255 256 257 |
# File 'lib/puppet/util/windows/file.rb', line 250 def readlink(link_name) link = nil open_symlink(link_name) do |handle| link = resolve_symlink(handle) end link end |
.remove_attributes(path, flags) ⇒ Object
143 144 145 146 147 148 149 |
# File 'lib/puppet/util/windows/file.rb', line 143 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
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/puppet/util/windows/file.rb', line 51 def replace_file(target, source) target_encoded = wide_string(target.to_s) source_encoded = wide_string(source.to_s) flags = 0x1 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
152 153 154 155 156 157 |
# File 'lib/puppet/util/windows/file.rb', line 152 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
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/puppet/util/windows/file.rb', line 299 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
82 83 84 85 86 87 88 89 |
# File 'lib/puppet/util/windows/file.rb', line 82 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
214 215 216 217 218 219 |
# File 'lib/puppet/util/windows/file.rb', line 214 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 |