Symlinks confuse the "What file system am I on?" logic. This patch just
runs the paths through a beefed up version of the standard 'realpath'
method.
Includes some of Markus's suggested changes.

Signed-off-by: Jesse Wolfe <[email protected]>
---
 lib/puppet/util/selinux.rb |   26 +++++++++++++++++++++-----
 spec/unit/util/selinux.rb  |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 57 insertions(+), 5 deletions(-)

diff --git a/lib/puppet/util/selinux.rb b/lib/puppet/util/selinux.rb
index bdf4415..133215a 100644
--- a/lib/puppet/util/selinux.rb
+++ b/lib/puppet/util/selinux.rb
@@ -13,6 +13,8 @@ rescue LoadError
     # Nothing
 end
 
+require 'pathname'
+
 module Puppet::Util::SELinux
 
     def selinux_support?
@@ -185,9 +187,24 @@ module Puppet::Util::SELinux
         return mntpoint
     end
 
+    def realpath(path)
+        pn   = Pathname.new(path)
+        rest = []
+        while ! pn.exist?
+            rest.unshift pn.basename
+            pn = pn.dirname
+        end
+        File.join( pn.realpath, *rest )
+    end
+
+    def parent_directory(path)
+        pn = Pathname.new(path)
+        pn.dirname.to_s
+    end
+
     # Internal helper function to return which type of filesystem a
     # given file path resides on
-    def find_fs(file)
+    def find_fs(path)
         unless mnts = read_mounts()
             return nil
         end
@@ -198,13 +215,12 @@ module Puppet::Util::SELinux
         # Just in case: return something if you're down to "/" or ""
         # Remove the last slash and everything after it,
         #   and repeat with that as the file for the next loop through.
-        ary = file.split('/')
-        while not ary.empty? do
-            path = ary.join('/')
+        path = realpath(path)
+        while not path.empty? do
             if mnts.has_key?(path)
                 return mnts[path]
             end
-            ary.pop
+            path = parent_directory(path)
         end
         return mnts['/']
     end
diff --git a/spec/unit/util/selinux.rb b/spec/unit/util/selinux.rb
index da4686e..0d1882d 100755
--- a/spec/unit/util/selinux.rb
+++ b/spec/unit/util/selinux.rb
@@ -61,6 +61,42 @@ describe Puppet::Util::SELinux do
             selinux_label_support?('/mnt/nfs/testfile').should be_false
         end
 
+        it "should follow symlinks when determining file systems" do
+            
self.stubs(:realpath).with('/mnt/symlink/testfile').returns('/mnt/nfs/dest/testfile')
+
+            selinux_label_support?('/mnt/symlink/testfile').should be_false
+        end
+
+    end
+
+    describe "realpath" do
+        it "should handle files that don't exist" do
+
+            # Since I'm stubbing Pathname.new for this test, 
+            # I need to also stub the internal calls to Pathname.new,
+            # which happen in Pathname.dirname and Parthname.basename
+            # I want those to return real Pathname objects,
+            # so I'm creating them before the stub is in place.
+            realpaths = Hash.new {|hash, path| hash[path] = Pathname.new(path) 
}
+            paths = ['symlink', '/mnt']
+            paths.each { |path| realpaths[path] }
+
+            realpaths['/mnt/symlink'] = stubs "Pathname"
+            
realpaths['/mnt/symlink'].stubs(:realpath).returns(realpaths['/mnt/nfs/dest'])
+            realpaths['/mnt/symlink'].stubs(:exist?).returns(true)
+
+            realpaths['/mnt/symlink/nonexistant'] = stubs "Pathname"
+            
realpaths['/mnt/symlink/nonexistant'].stubs(:realpath).raises(Errno::ENOENT)
+            realpaths['/mnt/symlink/nonexistant'].stubs(:exist?).returns(false)
+            
realpaths['/mnt/symlink/nonexistant'].stubs(:dirname).returns(realpaths['/mnt/symlink'])
+            
realpaths['/mnt/symlink/nonexistant'].stubs(:basename).returns(realpaths['nonexistant'])
+
+            realpaths.each do |path, value|
+                Pathname.stubs(:new).with(path).returns(value)
+            end
+
+            realpath('/mnt/symlink/nonexistant').should == 
'/mnt/nfs/dest/nonexistant'
+        end
     end
 
     describe "get_selinux_current_context" do
-- 
1.6.3.3

--

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.


Reply via email to