From: Trevor Vaughan <[email protected]>
Signed-off-by: Trevor Vaughan - Onyx Point <[email protected]> --- lib/puppet/type/file/mode.rb | 115 +++++++++++++++++++++++++++++++++-------- 1 files changed, 92 insertions(+), 23 deletions(-) diff --git a/lib/puppet/type/file/mode.rb b/lib/puppet/type/file/mode.rb index 83034cb..dd582cf 100755 --- a/lib/puppet/type/file/mode.rb +++ b/lib/puppet/type/file/mode.rb @@ -4,9 +4,8 @@ module Puppet Puppet::Type.type(:file).newproperty(:mode) do require 'etc' - desc "Mode the file should be. Currently relatively limited: - you must specify the exact mode the file should be. - + desc "Mode the file should be. You may specify either the precise octal mode or the POSIX symbolic mode per GNU coreutils chmod. + Note that when you set the mode of a directory, Puppet always sets the search/traverse (1) bit anywhere the read (4) bit is set. This is almost always what you want: read allows you to list the @@ -22,9 +21,74 @@ module Puppet In this case all of the files underneath ``/some/dir`` will have mode 644, and all of the directories will have mode 755." - @event = :file_changed + # This is a helper that takes a symbolic string and a file path and + # returns the adjusted decimal representation octal file mode (0700, + # etc...) + def sym2oct(str,path) + if str.to_s =~ /^\d+$/ + value = str + else + curmode = "00000" + if File.exists?(path) then + curmode = "%o" % File.stat(path).mode + curmode = curmode[-5 .. -1] + end + value = Integer(curmode) + + base = { + "u" => 6, + "g" => 3, + "o" => 0 + } + + left = { + "u" => 05700, + "g" => 03070, + "o" => 01007, + "a" => 07777 + } + + right = { + "r" => 00444, + "w" => 00222, + "x" => 00111, + "s" => 06000, + "t" => 01000, + "u" => 00700, + "g" => 00070, + "o" => 00007 + } + + reg = /^(([ugoa]+)([+-=])([rwxst]+|[ugo]),?)+$/ + + str.split(",").each do |cmd| + match = cmd.match(reg) or return curmode + # The following vars are directly dependent on the + # structure of the regex (reg) above + who = match[2] + what = match[3] + how = match[4].split(//).uniq.to_s + if how =~ /^[ugo]$/ then + who.split(//).uniq.each do |lhv| + right[how] = ( ((value << (base[lhv] - base[how])) & right[lhv]) | ( value & ~right[lhv] ) ) & 0777 + end + end + who = who.split(//).inject(num=0) {|num,b| num |= left[b]; num } + how = how.split(//).inject(num=0) {|num,b| num |= right[b]; num } + mask = who & how + case what + when "+": value = value | mask + when "-": value = value & ~mask + when "=": value = ( mask & who ) | ( value & ~(who & 0777) ) + end + end + end + Integer("0%o" % value) + end + + # Our modes are octal, so make sure they print correctly. Other # valid values are symbols, basically def is_to_s(currentvalue) @@ -52,29 +116,35 @@ module Puppet end munge do |should| - # this is pretty hackish, but i need to make sure the number is in - # octal, yet the number can only be specified as a string right now + # This handles both numbers and symbolic modes matching the regex + # /^(([ugoa]+)([+-=])([rwx]+),?)$/ + # + # Note: This now returns a string and the accepting function must + # know how to handle it! + lregex = /^(([ugoa]+)([+-=])([rwxst]+|[ugo]),?)+$/ + value = should + if value.is_a?(String) - unless value =~ /^\d+$/ - raise Puppet::Error, "File modes can only be numbers, not %s" % + if value =~ /^\d+$/ then + unless value =~ /^0/ + value = "0#{value}" + end + + old = value + begin + value = Integer(value) + rescue ArgumentError => detail + raise Puppet::DevError, "Could not convert %s to integer" % + old.inspect + end + elsif value.match(lregex).nil? then + raise Puppet::DevError, "Symbolic mode %s does not match #{lregex}" % value.inspect end - # Make sure our number looks like octal. - unless value =~ /^0/ - value = "0" + value - end - old = value - begin - value = Integer(value) - rescue ArgumentError => detail - raise Puppet::DevError, "Could not convert %s to integer" % - old.inspect - end end - - return value - end + return sym2oct(value,@resource[:path]) + end # If we're a directory, we need to be executable for all cases # that are readable. This should probably be selectable, but eh. @@ -121,7 +191,6 @@ module Puppet def sync mode = self.should - begin File.chmod(mode, @resource[:path]) rescue => detail -- 1.6.2.5 -- You received this message because you are subscribed to the Google Groups "Puppet Developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/puppet-dev?hl=en.
