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

Extended by:
FFI::Library, String
Defined in:
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

Class Method Summary collapse

Methods included from FFI::Library

attach_function_private

Methods included from String

wide_string

Class Method Details

.add_attributes(path, flags) ⇒ Object



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

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



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/puppet/util/windows/file.rb', line 135

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



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/puppet/util/windows/file.rb', line 160

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

.get_attributes(file_name) ⇒ Object



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

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

.get_file_attributes(file_name) ⇒ Object



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

def get_file_attributes(file_name)
  Puppet.deprecation_warning('Puppet::Util::Windows::File.get_file_attributes is deprecated; please use Puppet::Util::Windows::File.get_attributes')
  get_attributes(file_name)
end

.get_reparse_point_data(handle, &block) ⇒ Object



149
150
151
152
153
154
155
156
157
158
# File 'lib/puppet/util/windows/file.rb', line 149

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

.lstat(file_name) ⇒ Object



260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/puppet/util/windows/file.rb', line 260

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



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


208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/puppet/util/windows/file.rb', line 208

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


226
227
228
229
230
231
232
233
# File 'lib/puppet/util/windows/file.rb', line 226

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

  link
end

.remove_attributes(path, flags) ⇒ Object



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

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



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

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



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/puppet/util/windows/file.rb', line 236

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


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

Returns:

  • (Boolean)


187
188
189
190
191
192
193
194
195
# File 'lib/puppet/util/windows/file.rb', line 187

def symlink?(file_name)
  begin
    attributes = get_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