Class: Puppet::FileSystem::Windows Private

Inherits:
Posix show all
Defined in:
lib/puppet/file_system/windows.rb

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

Constant Summary collapse

FULL_CONTROL =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Puppet::Util::Windows::File::FILE_ALL_ACCESS
FILE_READ =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Puppet::Util::Windows::File::FILE_GENERIC_READ
FILE_NOT_FOUND =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

docs.microsoft.com/en-us/windows/desktop/debug/system-error-codes–0-499-

2
ACCESS_DENIED =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

5
SHARING_VIOLATION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

32
LOCK_VIOLATION =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

33

Instance Method Summary collapse

Methods inherited from Posix

#binread, #compare_stream

Methods inherited from FileImpl

#assert_path, #basename, #binread, #children, #compare_stream, #dir, #directory?, #each_line, #exclusive_create, #exclusive_open, #executable?, #file?, #mkpath, #path_string, #pathname, #read, #size, #touch, #writable?

Instance Method Details

#chmod(mode, path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



120
121
122
# File 'lib/puppet/file_system/windows.rb', line 120

def chmod(mode, path)
  Puppet::Util::Windows::Security.set_mode(mode, path.to_s)
end

#exist?(path) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


38
39
40
# File 'lib/puppet/file_system/windows.rb', line 38

def exist?(path)
  Puppet::Util::Windows::File.exist?(path)
end

#expand_path(path, dir_string = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/puppet/file_system/windows.rb', line 19

def expand_path(path, dir_string = nil)
  # ensure `nil` values behave like underlying File.expand_path
  string_path = ::File.expand_path(path.nil? ? nil : path_string(path), dir_string)
  # if no tildes, nothing to expand, no need to call Windows API, return original string
  return string_path unless string_path.index('~')

  begin
    # no need to do existence check up front as GetLongPathName implies that check is performed
    # and it should be the exception that files aren't actually present
    string_path = Puppet::Util::Windows::File.get_long_pathname(string_path)
  rescue Puppet::Util::Windows::Error => e
    # preserve original File.expand_path behavior for file / path not found by returning string
    raise if e.code != Puppet::Util::Windows::File::ERROR_FILE_NOT_FOUND &&
             e.code != Puppet::Util::Windows::File::ERROR_PATH_NOT_FOUND
  end

  string_path
end

#lstat(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



112
113
114
115
116
117
118
# File 'lib/puppet/file_system/windows.rb', line 112

def lstat(path)
  unless Puppet.features.manages_symlinks?
    return Puppet::Util::Windows::File.stat(path)
  end

  Puppet::Util::Windows::File.lstat(path)
end

#open(path, mode, options, &block) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Raises:

  • (TypeError)


10
11
12
13
14
15
16
17
# File 'lib/puppet/file_system/windows.rb', line 10

def open(path, mode, options, &block)
  # PUP-6959 mode is explicitly ignored until it can be implemented
  # Ruby on Windows uses mode for setting file attributes like read-only and
  # archived, not for setting permissions like POSIX
  raise TypeError, 'mode must be specified as an Integer' if mode && !mode.is_a?(Numeric)

  ::File.open(path, options, nil, &block)
end

#read_preserve_line_endings(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



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

def read_preserve_line_endings(path)
  contents = path.read(:mode => 'rb', :encoding => 'bom|utf-8')
  contents = path.read(:mode => 'rb', :encoding => "bom|#{Encoding.default_external.name}") unless contents.valid_encoding?
  contents = path.read unless contents.valid_encoding?

  contents
end

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



69
70
71
72
# File 'lib/puppet/file_system/windows.rb', line 69

def readlink(path)
  raise_if_symlinks_unsupported
  Puppet::Util::Windows::File.readlink(path)
end

#replace_file(path, mode = nil) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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
185
# File 'lib/puppet/file_system/windows.rb', line 138

def replace_file(path, mode = nil)
  if directory?(path)
    raise Errno::EISDIR, _("Is a directory: %{directory}") % { directory: path }
  end

  current_sid = Puppet::Util::Windows::SID.name_to_sid(Puppet::Util::Windows::ADSI::User.current_user_name)
  current_sid ||= Puppet::Util::Windows::SID.name_to_sid(Puppet::Util::Windows::ADSI::User.current_sam_compatible_user_name)

  dacl = case mode
         when 0o644
           dacl = secure_dacl(current_sid)
           dacl.allow(Puppet::Util::Windows::SID::BuiltinUsers, FILE_READ)
           dacl
         when 0o660, 0o640, 0o600, 0o440
           secure_dacl(current_sid)
         when nil
           get_dacl_from_file(path) || secure_dacl(current_sid)
         else
           raise ArgumentError, "#{mode} is invalid: Only modes 0644, 0640, 0660, and 0440 are allowed"
         end

  tempfile = Puppet::FileSystem::Uniquefile.new(Puppet::FileSystem.basename_string(path), Puppet::FileSystem.dir_string(path))
  begin
    tempdacl = Puppet::Util::Windows::AccessControlList.new
    tempdacl.allow(current_sid, FULL_CONTROL)
    set_dacl(tempfile.path, tempdacl)

    begin
      yield tempfile
      tempfile.flush
      tempfile.fsync
    ensure
      tempfile.close
    end

    set_dacl(tempfile.path, dacl) if dacl
    ::File.rename(tempfile.path, path_string(path))
  ensure
    tempfile.close!
  end
rescue Puppet::Util::Windows::Error => e
  case e.code
  when ACCESS_DENIED, SHARING_VIOLATION, LOCK_VIOLATION
    raise Errno::EACCES.new(path_string(path), e)
  else
    raise SystemCallError, e.message
  end
end

#stat(path) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



108
109
110
# File 'lib/puppet/file_system/windows.rb', line 108

def stat(path)
  Puppet::Util::Windows::File.stat(path)
end

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/puppet/file_system/windows.rb', line 42

def symlink(path, dest, options = {})
  raise_if_symlinks_unsupported

  dest_exists = exist?(dest) # returns false on dangling symlink
  dest_stat = Puppet::Util::Windows::File.stat(dest) if dest_exists

  # silent fail to preserve semantics of original FileUtils
  return 0 if dest_exists && dest_stat.ftype == 'directory'

  if dest_exists && dest_stat.ftype == 'file' && options[:force] != true
    raise(Errno::EEXIST, _("%{dest} already exists and the :force option was not specified") % { dest: dest })
  end

  if options[:noop] != true
    ::File.delete(dest) if dest_exists # can only be file
    Puppet::Util::Windows::File.symlink(path, dest)
  end

  0
end

#symlink?(path) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


63
64
65
66
67
# File 'lib/puppet/file_system/windows.rb', line 63

def symlink?(path)
  return false unless Puppet.features.manages_symlinks?

  Puppet::Util::Windows::File.symlink?(path)
end

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/puppet/file_system/windows.rb', line 74

def unlink(*file_names)
  unless Puppet.features.manages_symlinks?
    return ::File.unlink(*file_names)
  end

  file_names.each do |file_name|
    file_name = file_name.to_s # handle PathName
    stat = begin
      Puppet::Util::Windows::File.stat(file_name)
    rescue
      nil
    end

    # sigh, Ruby + Windows :(
    if !stat
      begin
        ::File.unlink(file_name)
      rescue
        Dir.rmdir(file_name)
      end
    elsif stat.ftype == 'directory'
      if Puppet::Util::Windows::File.symlink?(file_name)
        Dir.rmdir(file_name)
      else
        raise Errno::EPERM, file_name
      end
    else
      ::File.unlink(file_name)
    end
  end

  file_names.length
end