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

Defined in:
lib/puppet/util/windows/file.rb

Defined Under Namespace

Modules: API

Constant Summary collapse

MoveFileEx =
Windows::API.new('MoveFileExW', 'PPL', 'B')
INVALID_FILE_ATTRIBUTES =

define INVALID_FILE_ATTRIBUTES (DWORD (-1))

0xFFFFFFFF
INVALID_HANDLE_VALUE =

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

-1 #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
FILE_ATTRIBUTE_REPARSE_POINT =
0x400
GENERIC_READ =
0x80000000
FILE_SHARE_READ =
1
OPEN_EXISTING =
3
FILE_FLAG_OPEN_REPARSE_POINT =
0x00200000
FILE_FLAG_BACKUP_SEMANTICS =
0x02000000

Class Method Summary collapse

Class Method Details

.create_file(file_name, desired_access, share_mode, security_attributes, creation_disposition, flags_and_attributes, template_file_handle) ⇒ Object



144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/puppet/util/windows/file.rb', line 144

def self.create_file(file_name, desired_access, share_mode, security_attributes,
  creation_disposition, flags_and_attributes, template_file_handle)

  result = API.create_file(Puppet::Util::Windows::String.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



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/puppet/util/windows/file.rb', line 158

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

  result = API.device_io_control(
    handle,
    io_control_code,
    in_buffer, in_buffer.nil? ? 0 : in_buffer.size,
    out_buffer, out_buffer.size,
    FFI::MemoryPointer.new(:uint, 1),
    nil
  )

  return out_buffer if result
  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

.get_file_attributes(file_name) ⇒ Object



137
138
139
140
141
# File 'lib/puppet/util/windows/file.rb', line 137

def self.get_file_attributes(file_name)
  result = API.get_file_attributes(Puppet::Util::Windows::String.wide_string(file_name.to_s))
  return result unless result == INVALID_FILE_ATTRIBUTES
  raise Puppet::Util::Windows::Error.new("GetFileAttributes(#{file_name})")
end

.lstat(file_name) ⇒ Object



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/puppet/util/windows/file.rb', line 243

def lstat(file_name)
  file_name = file_name.to_s # accomodate 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



28
29
30
31
32
33
34
35
# File 'lib/puppet/util/windows/file.rb', line 28

def move_file_ex(source, target, flags = 0)
  result = MoveFileEx.call(Puppet::Util::Windows::String.wide_string(source.to_s),
                           Puppet::Util::Windows::String.wide_string(target.to_s),
                           flags)
  return true unless result == 0
  raise Puppet::Util::Windows::Error.
    new("MoveFileEx(#{source}, #{target}, #{flags.to_s(8)})")
end


197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'lib/puppet/util/windows/file.rb', line 197

def self.open_symlink(link_name)
  begin
    yield handle = create_file(
    Puppet::Util::Windows::String.wide_string(link_name.to_s),
    GENERIC_READ,
    FILE_SHARE_READ,
    nil, # security_attributes
    OPEN_EXISTING,
    FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
    0) # template_file
  ensure
    API.close_handle(handle) if handle
  end
end


212
213
214
215
216
# File 'lib/puppet/util/windows/file.rb', line 212

def readlink(link_name)
  open_symlink(link_name) do |handle|
    resolve_symlink(handle)
  end
end

.replace_file(target, source) ⇒ Object



7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/puppet/util/windows/file.rb', line 7

def replace_file(target, source)
  target_encoded = Puppet::Util::Windows::String.wide_string(target.to_s)
  source_encoded = Puppet::Util::Windows::String.wide_string(source.to_s)

  flags = 0x1
  backup_file = nil
  result = API.replace_file(
    target_encoded,
    source_encoded,
    backup_file,
    flags,
    0,
    0
  )

  return true if result
  raise Puppet::Util::Windows::Error.new("ReplaceFile(#{target}, #{source})")
end

.stat(file_name) ⇒ Object



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

def stat(file_name)
  file_name = file_name.to_s # accomodate 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


126
127
128
129
130
131
132
133
# File 'lib/puppet/util/windows/file.rb', line 126

def symlink(target, symlink)
  flags = File.directory?(target) ? 0x1 : 0x0
  result = API.create_symbolic_link(Puppet::Util::Windows::String.wide_string(symlink.to_s),
    Puppet::Util::Windows::String.wide_string(target.to_s), flags)
  return true if result
  raise Puppet::Util::Windows::Error.new(
    "CreateSymbolicLink(#{symlink}, #{target}, #{flags.to_s(8)})")
end

.symlink?(file_name) ⇒ Boolean

Returns:

  • (Boolean)


180
181
182
183
184
185
186
187
188
# File 'lib/puppet/util/windows/file.rb', line 180

def symlink?(file_name)
  begin
    attributes = get_file_attributes(file_name)
    (attributes & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT
  rescue
    # raised INVALID_FILE_ATTRIBUTES is equivalent to file not found
    false
  end
end