Module: Puppet::Util::Windows::File

Extended by:
FFI::Windows::Functions, FFI::Windows::Structs, String
Includes:
FFI::Windows::Constants, FFI::Windows::Functions, FFI::Windows::Structs
Defined in:
lib/puppet/util/windows.rb,
lib/puppet/util/windows/file.rb

Constant Summary collapse

INVALID_HANDLE_VALUE =

define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)

FFI::Pointer.new(-1).address

Constants included from FFI::Windows::Structs

FFI::Windows::Structs::MAXIMUM_REPARSE_DATA_BUFFER_SIZE

Constants included from FFI::Windows::Functions

FFI::Windows::Functions::SC_ENUM_TYPE, FFI::Windows::Functions::SC_STATUS_TYPE

Constants included from FFI::Windows::Constants

FFI::Windows::Constants::ABOVE_NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::ALL_SERVICE_TYPES, FFI::Windows::Constants::BELOW_NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::CREATE_BREAKAWAY_FROM_JOB, FFI::Windows::Constants::CREATE_DEFAULT_ERROR_MODE, FFI::Windows::Constants::CREATE_NEW_CONSOLE, FFI::Windows::Constants::CREATE_NEW_PROCESS_GROUP, FFI::Windows::Constants::CREATE_NO_WINDOW, FFI::Windows::Constants::CREATE_PRESERVE_CODE_AUTHZ_LEVEL, FFI::Windows::Constants::CREATE_PROTECTED_PROCESS, FFI::Windows::Constants::CREATE_SEPARATE_WOW_VDM, FFI::Windows::Constants::CREATE_SHARED_WOW_VDM, FFI::Windows::Constants::CREATE_SUSPENDED, FFI::Windows::Constants::CREATE_UNICODE_ENVIRONMENT, FFI::Windows::Constants::DEBUG_ONLY_THIS_PROCESS, FFI::Windows::Constants::DEBUG_PROCESS, FFI::Windows::Constants::DELETE, FFI::Windows::Constants::DETACHED_PROCESS, FFI::Windows::Constants::ERROR_ALREADY_EXISTS, FFI::Windows::Constants::ERROR_FILE_NOT_FOUND, FFI::Windows::Constants::ERROR_PATH_NOT_FOUND, FFI::Windows::Constants::ERROR_SERVICE_DOES_NOT_EXIST, FFI::Windows::Constants::FILE_ALL_ACCESS, FFI::Windows::Constants::FILE_APPEND_DATA, FFI::Windows::Constants::FILE_ATTRIBUTE_DIRECTORY, FFI::Windows::Constants::FILE_ATTRIBUTE_READONLY, FFI::Windows::Constants::FILE_ATTRIBUTE_REPARSE_POINT, FFI::Windows::Constants::FILE_DELETE_CHILD, FFI::Windows::Constants::FILE_DEVICE_FILE_SYSTEM, FFI::Windows::Constants::FILE_EXECUTE, FFI::Windows::Constants::FILE_FLAG_BACKUP_SEMANTICS, FFI::Windows::Constants::FILE_FLAG_OPEN_REPARSE_POINT, FFI::Windows::Constants::FILE_GENERIC_EXECUTE, FFI::Windows::Constants::FILE_GENERIC_READ, FFI::Windows::Constants::FILE_GENERIC_WRITE, FFI::Windows::Constants::FILE_READ_ATTRIBUTES, FFI::Windows::Constants::FILE_READ_DATA, FFI::Windows::Constants::FILE_READ_EA, FFI::Windows::Constants::FILE_SHARE_READ, FFI::Windows::Constants::FILE_SHARE_WRITE, FFI::Windows::Constants::FILE_WRITE_ATTRIBUTES, FFI::Windows::Constants::FILE_WRITE_DATA, FFI::Windows::Constants::FILE_WRITE_EA, FFI::Windows::Constants::FINAL_STATES, FFI::Windows::Constants::FSCTL_GET_REPARSE_POINT, FFI::Windows::Constants::GENERIC_ALL, FFI::Windows::Constants::GENERIC_EXECUTE, FFI::Windows::Constants::GENERIC_READ, FFI::Windows::Constants::GENERIC_WRITE, FFI::Windows::Constants::HANDLE_FLAG_INHERIT, FFI::Windows::Constants::HIGH_PRIORITY_CLASS, FFI::Windows::Constants::IDLE_PRIORITY_CLASS, FFI::Windows::Constants::INHERIT_PARENT_AFFINITY, FFI::Windows::Constants::INVALID_FILE_ATTRIBUTES, FFI::Windows::Constants::IO_REPARSE_TAG_CSV, FFI::Windows::Constants::IO_REPARSE_TAG_DEDUP, FFI::Windows::Constants::IO_REPARSE_TAG_DFS, FFI::Windows::Constants::IO_REPARSE_TAG_DFSR, FFI::Windows::Constants::IO_REPARSE_TAG_HSM, FFI::Windows::Constants::IO_REPARSE_TAG_HSM2, FFI::Windows::Constants::IO_REPARSE_TAG_MOUNT_POINT, FFI::Windows::Constants::IO_REPARSE_TAG_NFS, FFI::Windows::Constants::IO_REPARSE_TAG_SIS, FFI::Windows::Constants::IO_REPARSE_TAG_SYMLINK, FFI::Windows::Constants::IO_REPARSE_TAG_WIM, FFI::Windows::Constants::LOGON_WITH_PROFILE, FFI::Windows::Constants::MAXIMUM_REPARSE_DATA_BUFFER_SIZE, FFI::Windows::Constants::METHOD_BUFFERED, FFI::Windows::Constants::NORMAL_PRIORITY_CLASS, FFI::Windows::Constants::OPEN_EXISTING, FFI::Windows::Constants::PROCESS_ALL_ACCESS, FFI::Windows::Constants::PROCESS_QUERY_INFORMATION, FFI::Windows::Constants::PROCESS_SET_INFORMATION, FFI::Windows::Constants::PROCESS_TERMINATE, FFI::Windows::Constants::PROCESS_VM_READ, FFI::Windows::Constants::REALTIME_PRIORITY_CLASS, FFI::Windows::Constants::REPLACEFILE_IGNORE_ACL_ERRORS, FFI::Windows::Constants::REPLACEFILE_IGNORE_MERGE_ERRORS, FFI::Windows::Constants::REPLACEFILE_WRITE_THROUGH, FFI::Windows::Constants::SC_MANAGER_ALL_ACCESS, FFI::Windows::Constants::SC_MANAGER_CONNECT, FFI::Windows::Constants::SC_MANAGER_CREATE_SERVICE, FFI::Windows::Constants::SC_MANAGER_ENUMERATE_SERVICE, FFI::Windows::Constants::SC_MANAGER_LOCK, FFI::Windows::Constants::SC_MANAGER_MODIFY_BOOT_CONFIG, FFI::Windows::Constants::SC_MANAGER_QUERY_LOCK_STATUS, FFI::Windows::Constants::SEM_FAILCRITICALERRORS, FFI::Windows::Constants::SEM_NOGPFAULTERRORBOX, FFI::Windows::Constants::SERVICENAME_MAX, FFI::Windows::Constants::SERVICE_ACCEPT_HARDWAREPROFILECHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_NETBINDCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_PARAMCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_PAUSE_CONTINUE, FFI::Windows::Constants::SERVICE_ACCEPT_POWEREVENT, FFI::Windows::Constants::SERVICE_ACCEPT_PRESHUTDOWN, FFI::Windows::Constants::SERVICE_ACCEPT_SESSIONCHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_SHUTDOWN, FFI::Windows::Constants::SERVICE_ACCEPT_STOP, FFI::Windows::Constants::SERVICE_ACCEPT_TIMECHANGE, FFI::Windows::Constants::SERVICE_ACCEPT_TRIGGEREVENT, FFI::Windows::Constants::SERVICE_ACCEPT_USER_LOGOFF, FFI::Windows::Constants::SERVICE_ACTIVE, FFI::Windows::Constants::SERVICE_ALL_ACCESS, FFI::Windows::Constants::SERVICE_AUTO_START, FFI::Windows::Constants::SERVICE_BOOT_START, FFI::Windows::Constants::SERVICE_CHANGE_CONFIG, FFI::Windows::Constants::SERVICE_CONFIG_DELAYED_AUTO_START_INFO, FFI::Windows::Constants::SERVICE_CONFIG_DESCRIPTION, FFI::Windows::Constants::SERVICE_CONFIG_FAILURE_ACTIONS, FFI::Windows::Constants::SERVICE_CONFIG_FAILURE_ACTIONS_FLAG, FFI::Windows::Constants::SERVICE_CONFIG_LAUNCH_PROTECTED, FFI::Windows::Constants::SERVICE_CONFIG_PREFERRED_NODE, FFI::Windows::Constants::SERVICE_CONFIG_PRESHUTDOWN_INFO, FFI::Windows::Constants::SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO, FFI::Windows::Constants::SERVICE_CONFIG_SERVICE_SID_INFO, FFI::Windows::Constants::SERVICE_CONFIG_TRIGGER_INFO, FFI::Windows::Constants::SERVICE_CONFIG_TYPES, FFI::Windows::Constants::SERVICE_CONTINUE_PENDING, FFI::Windows::Constants::SERVICE_CONTROL_CONTINUE, FFI::Windows::Constants::SERVICE_CONTROL_DEVICEEVENT, FFI::Windows::Constants::SERVICE_CONTROL_HARDWAREPROFILECHANGE, FFI::Windows::Constants::SERVICE_CONTROL_INTERROGATE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDADD, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDDISABLE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDENABLE, FFI::Windows::Constants::SERVICE_CONTROL_NETBINDREMOVE, FFI::Windows::Constants::SERVICE_CONTROL_PARAMCHANGE, FFI::Windows::Constants::SERVICE_CONTROL_PAUSE, FFI::Windows::Constants::SERVICE_CONTROL_POWEREVENT, FFI::Windows::Constants::SERVICE_CONTROL_PRESHUTDOWN, FFI::Windows::Constants::SERVICE_CONTROL_SESSIONCHANGE, FFI::Windows::Constants::SERVICE_CONTROL_SHUTDOWN, FFI::Windows::Constants::SERVICE_CONTROL_SIGNALS, FFI::Windows::Constants::SERVICE_CONTROL_STOP, FFI::Windows::Constants::SERVICE_CONTROL_TIMECHANGE, FFI::Windows::Constants::SERVICE_CONTROL_TRIGGEREVENT, FFI::Windows::Constants::SERVICE_DEMAND_START, FFI::Windows::Constants::SERVICE_DISABLED, FFI::Windows::Constants::SERVICE_ENUMERATE_DEPENDENTS, FFI::Windows::Constants::SERVICE_FILE_SYSTEM_DRIVER, FFI::Windows::Constants::SERVICE_INACTIVE, FFI::Windows::Constants::SERVICE_INTERACTIVE_PROCESS, FFI::Windows::Constants::SERVICE_INTERROGATE, FFI::Windows::Constants::SERVICE_KERNEL_DRIVER, FFI::Windows::Constants::SERVICE_NO_CHANGE, FFI::Windows::Constants::SERVICE_PAUSED, FFI::Windows::Constants::SERVICE_PAUSE_CONTINUE, FFI::Windows::Constants::SERVICE_PAUSE_PENDING, FFI::Windows::Constants::SERVICE_QUERY_CONFIG, FFI::Windows::Constants::SERVICE_QUERY_STATUS, FFI::Windows::Constants::SERVICE_RUNNING, FFI::Windows::Constants::SERVICE_START, FFI::Windows::Constants::SERVICE_START_PENDING, FFI::Windows::Constants::SERVICE_START_TYPES, FFI::Windows::Constants::SERVICE_STATES, FFI::Windows::Constants::SERVICE_STATE_ALL, FFI::Windows::Constants::SERVICE_STOP, FFI::Windows::Constants::SERVICE_STOPPED, FFI::Windows::Constants::SERVICE_STOP_PENDING, FFI::Windows::Constants::SERVICE_SYSTEM_START, FFI::Windows::Constants::SERVICE_USER_DEFINED_CONTROL, FFI::Windows::Constants::SERVICE_USER_OWN_PROCESS, FFI::Windows::Constants::SERVICE_USER_SHARE_PROCESS, FFI::Windows::Constants::SERVICE_WIN32_OWN_PROCESS, FFI::Windows::Constants::SERVICE_WIN32_SHARE_PROCESS, FFI::Windows::Constants::SHGFI_DISPLAYNAME, FFI::Windows::Constants::SHGFI_PIDL, FFI::Windows::Constants::SPECIFIC_RIGHTS_ALL, FFI::Windows::Constants::STANDARD_RIGHTS_ALL, FFI::Windows::Constants::STANDARD_RIGHTS_EXECUTE, FFI::Windows::Constants::STANDARD_RIGHTS_READ, FFI::Windows::Constants::STANDARD_RIGHTS_REQUIRED, FFI::Windows::Constants::STANDARD_RIGHTS_WRITE, FFI::Windows::Constants::STARTF_USESTDHANDLES, FFI::Windows::Constants::SYNCHRONIZE, FFI::Windows::Constants::TOKEN_INFORMATION_CLASS, FFI::Windows::Constants::UNSAFE_PENDING_STATES, FFI::Windows::Constants::WRITE_DAC, FFI::Windows::Constants::WRITE_OWNER

Class Method Summary collapse

Methods included from String

wide_string

Class Method Details

.add_attributes(path, flags) ⇒ Object



100
101
102
103
104
105
106
# File 'lib/puppet/util/windows/file.rb', line 100

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



128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/puppet/util/windows/file.rb', line 128

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, "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



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/puppet/util/windows/file.rb', line 181

def self.device_io_control(handle, io_control_code, in_buffer = nil, out_buffer = nil)
  if out_buffer.nil?
    raise Puppet::Util::Windows::Error, _("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, "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

Returns:

  • (Boolean)


58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/puppet/util/windows/file.rb', line 58

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
    reparse_point = (result & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT
    if reparse_point && symlink_reparse_point?(path)
      # walk the symlink and try again...
      seen_paths << path.downcase
      path = readlink(path)
    else
      # file was found and its not a symlink
      return true
    end
  end

  false
end

.get_attributes(file_name, raise_on_invalid = true) ⇒ Object



90
91
92
93
94
95
96
97
# File 'lib/puppet/util/windows/file.rb', line 90

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, "GetFileAttributes(#{file_name})"
  end

  result
end

.get_long_pathname(path) ⇒ Object



250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/puppet/util/windows/file.rb', line 250

def get_long_pathname(path)
  converted = ''.dup
  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, _("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



142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/puppet/util/windows/file.rb', line 142

def self.get_reparse_point_data(handle, &block)
  # must be multiple of 1024, min 10240
  FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
    device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)

    reparse_tag = reparse_data_buffer_ptr.read_win32_ulong
    buffer_type = case reparse_tag
                  when IO_REPARSE_TAG_SYMLINK
                    SYMLINK_REPARSE_DATA_BUFFER
                  when IO_REPARSE_TAG_MOUNT_POINT
                    MOUNT_POINT_REPARSE_DATA_BUFFER
                  when IO_REPARSE_TAG_NFS
                    raise Puppet::Util::Windows::Error, "Retrieving NFS reparse point data is unsupported"
                  else
                    raise Puppet::Util::Windows::Error, "DeviceIoControl(#{handle}, " \
                                                        "FSCTL_GET_REPARSE_POINT) returned unknown tag 0x#{reparse_tag.to_s(16).upcase}"
                  end

    yield buffer_type.new(reparse_data_buffer_ptr)
  end

  # underlying struct MemoryPointer has been cleaned up by this point, nothing to return
  nil
end

.get_reparse_point_tag(handle) ⇒ Object



167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/puppet/util/windows/file.rb', line 167

def self.get_reparse_point_tag(handle)
  reparse_tag = nil

  # must be multiple of 1024, min 10240
  FFI::MemoryPointer.new(MAXIMUM_REPARSE_DATA_BUFFER_SIZE) do |reparse_data_buffer_ptr|
    device_io_control(handle, FSCTL_GET_REPARSE_POINT, nil, reparse_data_buffer_ptr)

    # DWORD ReparseTag is the first member of the struct
    reparse_tag = reparse_data_buffer_ptr.read_win32_ulong
  end

  reparse_tag
end

.get_short_pathname(path) ⇒ Object



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/puppet/util/windows/file.rb', line 268

def get_short_pathname(path)
  converted = ''.dup
  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, "Failed to call GetShortPathName"
      end

      converted = converted_ptr.read_wide_string(buffer_size - 1)
    end
  end

  converted
end

.lstat(file_name) ⇒ Object



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/puppet/util/windows/file.rb', line 310

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



37
38
39
40
41
42
43
44
45
# File 'lib/puppet/util/windows/file.rb', line 37

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, "MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})"
end


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/puppet/util/windows/file.rb', line 221

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


240
241
242
243
244
245
246
247
# File 'lib/puppet/util/windows/file.rb', line 240

def readlink(link_name)
  link = nil
  open_symlink(link_name) do |handle|
    link = resolve_symlink(handle)
  end

  link
end

.remove_attributes(path, flags) ⇒ Object



109
110
111
112
113
114
115
# File 'lib/puppet/util/windows/file.rb', line 109

def remove_attributes(path, flags)
  oldattrs = get_attributes(path)

  if (oldattrs & ~flags) != oldattrs
    set_attributes(path, oldattrs & ~flags)
  end
end

.reparse_point?(file_name) ⇒ Boolean

Returns:

  • (Boolean)


206
207
208
209
210
211
212
# File 'lib/puppet/util/windows/file.rb', line 206

def reparse_point?(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

.replace_file(target, source) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/puppet/util/windows/file.rb', line 16

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, "ReplaceFile(#{target}, #{source})"
end

.set_attributes(path, flags) ⇒ Object



118
119
120
121
122
123
# File 'lib/puppet/util/windows/file.rb', line 118

def set_attributes(path, flags)
  success = SetFileAttributesW(wide_string(path), flags) != FFI::WIN32_FALSE
  raise Puppet::Util::Windows::Error, _("Failed to set file attributes") unless success

  success
end

.stat(file_name) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
# File 'lib/puppet/util/windows/file.rb', line 286

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


48
49
50
51
52
53
54
55
# File 'lib/puppet/util/windows/file.rb', line 48

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, "CreateSymbolicLink(#{symlink}, #{target}, #{flags.to_s(8)})"
end

.symlink?(file_name) ⇒ Boolean

Returns:

  • (Boolean)


215
216
217
218
# File 'lib/puppet/util/windows/file.rb', line 215

def symlink?(file_name)
  # Puppet currently only handles mount point and symlink reparse points, ignores others
  reparse_point?(file_name) && symlink_reparse_point?(file_name)
end