From: Trevor Vaughan <[email protected]>
Signed-off-by: Trevor Vaughan - Onyx Point <[email protected]>
---
lib/puppet/type/file.rb | 2 +-
lib/puppet/type/file/mode.rb | 141 ++++++++++++++++++++++++++++++++
+---------
spec/unit/type/file/mode.rb | 61 ++++++++++++++++++
3 files changed, 173 insertions(+), 31 deletions(-)
create mode 100755 spec/unit/type/file/mode.rb
diff --git a/lib/puppet/type/file.rb b/lib/puppet/type/file.rb
index 2f5b5df..ede4b1a 100644
--- a/lib/puppet/type/file.rb
+++ b/lib/puppet/type/file.rb
@@ -725,7 +725,7 @@ module Puppet
path = self[:path]
end
- mode = self.should(:mode) # might be nil
+ mode = self.should(:mode) ?
self.property(:mode).sym2oct(self.stat,self.should(:mode)) : nil #
might be nil
umask = mode ? 000 : 022
Puppet::Util.withumask(umask) do
diff --git a/lib/puppet/type/file/mode.rb b/lib/puppet/type/file/
mode.rb
index 83034cb..da0d09d 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,16 +21,90 @@ 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
+ # The bitwise position of the UGO fields.
+ SYMBASE = {
+ "u" => 6,
+ "g" => 3,
+ "o" => 0
+ }
+
+ # The general mask for activating the appropriate sections
of 'how'.
+ SYMLEFT = {
+ "u" => 05700,
+ "g" => 03070,
+ "o" => 01007,
+ "a" => 07777
+ }
+ # The regular expression for matching a valid symbolic mode.
+ SYMREG = /^(([ugoa]+)([+-=])([rwxst]+|[ugo]),?)+$/
+
+ # This is a helper that takes the current mode and the new
mode and
+ # returns the adjusted decimal representation octal file
mode (0700,
+ # etc...)
+ #
+ # The current mode (curmode) can be represented either as
an integer
+ # string or as a File::Stat object.
+ def sym2oct(curmode,newmode)
+ if !newmode.nil? and newmode.to_s =~ /^\d+$/ then
+ value = newmode
+ else
+ # Set this to 0600 so that we can actually read and
write the
+ # file as a normal user.
+ if curmode.nil? then
+ value = 00600
+ elsif curmode.is_a?(File::Stat) then
+ value = curmode.mode & 07777
+ else
+ value = Integer("0#{curmode}")
+ end
+
+ # This needs to remain variable.
+ right = {
+ "r" => 00444,
+ "w" => 00222,
+ "x" => 00111,
+ "s" => 06000,
+ "t" => 01000,
+ "u" => 00700,
+ "g" => 00070,
+ "o" => 00007
+ }
+
+ newmode.split(",").each do |cmd|
+ match = cmd.match(SYMREG) or return value
+ # The following vars are directly dependent on
the
+ # structure of SYMREG 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 << (SYMBASE[lhv] -
SYMBASE[how])) & right[lhv]) | ( value & ~right[lhv] ) ) & 0777
+ end
+ end
+ who = who.split(//).inject(num=0) {|num,b| num |
= SYMLEFT[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
+ value = "0%o" % value
+ end
+ Integer(value)
+ end
+
+
# Our modes are octal, so make sure they print correctly.
Other
# valid values are symbols, basically
def is_to_s(currentvalue)
- case currentvalue
- when Integer
+ if currentvalue.is_a?(Integer) then
return "%o" % currentvalue
- when Symbol
+ elsif ( currentvalue.is_a?(Symbol) or
( currentvalue.is_a?(String) and currentvalue.match(SYMREG))) then
return currentvalue
else
raise Puppet::DevError, "Invalid current value for
mode: %s" %
@@ -40,10 +113,9 @@ module Puppet
end
def should_to_s(newvalue = @should)
- case newvalue
- when Integer
+ if newvalue.is_a?(Integer) then
return "%o" % newvalue
- when Symbol
+ elsif ( newvalue.is_a?(Symbol) or ( newvalue.is_a?
(String) and newvalue.match(SYMREG))) then
return newvalue
else
raise Puppet::DevError, "Invalid 'should' value for
mode: %s" %
@@ -52,29 +124,32 @@ 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
SYMREG
+ #
+ # Note: This now returns a string and the accepting
function must
+ # know how to handle it!
+
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(SYMREG).nil? then
+ raise Puppet::DevError, "Symbolic mode %s does
not match #{SYMREG}" %
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
+ end
# If we're a directory, we need to be executable for all cases
# that are readable. This should probably be selectable,
but eh.
@@ -99,7 +174,14 @@ module Puppet
self.debug "Not managing symlink mode"
return true
else
- return super(currentvalue)
+ retval = super(currentvalue)
+ if !retval then
+ if currentvalue ==
sym2oct(resource.stat,self.should) then
+ retval = true
+ end
+ end
+
+ return retval
end
end
@@ -120,8 +202,7 @@ module Puppet
end
def sync
- mode = self.should
-
+ mode = sym2oct(resource.stat,self.should)
begin
File.chmod(mode, @resource[:path])
rescue => detail
diff --git a/spec/unit/type/file/mode.rb b/spec/unit/type/file/mode.rb
new file mode 100755
index 0000000..4cdbc36
--- /dev/null
+++ b/spec/unit/type/file/mode.rb
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+
+Dir.chdir(File.dirname(__FILE__)) { (s = lambda { |f| File.exist?
(f) ? require(f) : Dir.chdir("..") { s.call(f) } }).call("spec/
spec_helper.rb") }
+
+property = Puppet::Type.type(:file).attrclass(:mode)
+
+describe property do
+ before do
+ @resource = stub 'resource', :line => "foo", :file => "bar"
+ @mode = property.new :resource => @resource
+ end
+
+ it "should have a method for converting symbolic modes to octal
modes" do
+ @mode.must respond_to(:sym2oct)
+ end
+ it "should be able to apply three digit numeric octal modes" do
+ @mode.sym2oct("777",Integer("0640")).should ==
Integer("0640")
+ end
+ it "should be able to apply additive symbolic user modes" do
+ @mode.sym2oct("640","u+x").should == Integer("0740")
+ end
+ it "should be able to apply subtractive symbolic user modes" do
+ @mode.sym2oct("640","u-w").should == Integer("0440")
+ end
+ it "should be able to apply equality symbolic user modes" do
+ @mode.sym2oct("640","u=r").should == Integer("0440")
+ end
+ it "should be able to apply referential equality symbolic user
modes" do
+ @mode.sym2oct("640","u=g").should == Integer("0440")
+ end
+ it "should be able to apply additive symbolic group modes" do
+ @mode.sym2oct("640","g+x").should == Integer("0650")
+ end
+ it "should be able to apply subtractive symbolic group modes" do
+ @mode.sym2oct("640","g-r").should == Integer("0600")
+ end
+ it "should be able to apply equality symbolic group modes" do
+ @mode.sym2oct("640","g=rwx").should == Integer("0670")
+ end
+ it "should be able to apply referential equality symbolic group
modes" do
+ @mode.sym2oct("640","g=o").should == Integer("0600")
+ end
+ it "should be able to apply additive symbolic other modes" do
+ @mode.sym2oct("640","o+rx").should == Integer("0645")
+ end
+ it "should be able to apply subtractive symbolic other modes" do
+ @mode.sym2oct("647","o-rx").should == Integer("0642")
+ end
+ it "should be able to apply equality symbolic other modes" do
+ @mode.sym2oct("647","o-rx").should == Integer("0642")
+ end
+ it "should be able to apply referential equality symbolic other
modes" do
+ @mode.sym2oct("647","o=u").should == Integer("0646")
+ end
+ it "should be able to apply multi-part modes" do
+ @mode.sym2oct("640","o=u,g=o,u-w").should == Integer("0466")
+ end
+ it "should not be able to apply invalid modes" do
+ @mode.sym2oct("640","go-write-a-letter").should ==
Integer("0640")
+ end
+end
--
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
.