diff --git a/lib/puppet/provider/file/posix.rb b/lib/puppet/provider/file/posix.rb index 0ce7d223e..7fab90bf7 100644 --- a/lib/puppet/provider/file/posix.rb +++ b/lib/puppet/provider/file/posix.rb @@ -1,136 +1,136 @@ Puppet::Type.type(:file).provide :posix do desc "Uses POSIX functionality to manage file ownership and permissions." confine :feature => :posix has_features :manages_symlinks include Puppet::Util::POSIX include Puppet::Util::Warnings require 'etc' def uid2name(id) return id.to_s if id.is_a?(Symbol) or id.is_a?(String) return nil if id > Puppet[:maximum_uid].to_i begin user = Etc.getpwuid(id) rescue TypeError, ArgumentError return nil end if user.uid == "" return nil else return user.name end end # Determine if the user is valid, and if so, return the UID def name2uid(value) Integer(value) rescue uid(value) || false end def gid2name(id) return id.to_s if id.is_a?(Symbol) or id.is_a?(String) return nil if id > Puppet[:maximum_uid].to_i begin group = Etc.getgrgid(id) rescue TypeError, ArgumentError return nil end if group.gid == "" return nil else return group.name end end def name2gid(value) Integer(value) rescue gid(value) || false end def owner unless stat = resource.stat return :absent end currentvalue = stat.uid # On OS X, files that are owned by -2 get returned as really # large UIDs instead of negative ones. This isn't a Ruby bug, # it's an OS X bug, since it shows up in perl, too. if currentvalue > Puppet[:maximum_uid].to_i self.warning "Apparently using negative UID (#{currentvalue}) on a platform that does not consistently handle them" currentvalue = :silly end currentvalue end def owner=(should) # Set our method appropriately, depending on links. if resource[:links] == :manage method = :lchown else method = :chown end begin File.send(method, should, nil, resource[:path]) rescue => detail raise Puppet::Error, "Failed to set owner to '#{should}': #{detail}", detail.backtrace end end def group return :absent unless stat = resource.stat currentvalue = stat.gid # On OS X, files that are owned by -2 get returned as really # large GIDs instead of negative ones. This isn't a Ruby bug, # it's an OS X bug, since it shows up in perl, too. if currentvalue > Puppet[:maximum_uid].to_i self.warning "Apparently using negative GID (#{currentvalue}) on a platform that does not consistently handle them" currentvalue = :silly end currentvalue end def group=(should) # Set our method appropriately, depending on links. if resource[:links] == :manage method = :lchown else method = :chown end begin File.send(method, nil, should, resource[:path]) rescue => detail raise Puppet::Error, "Failed to set group to '#{should}': #{detail}", detail.backtrace end end def mode if stat = resource.stat - return (stat.mode & 007777).to_s(8) + return (stat.mode & 007777).to_s(8).rjust(4, '0') else return :absent end end def mode=(value) begin File.chmod(value.to_i(8), resource[:path]) rescue => detail error = Puppet::Error.new("failed to set mode #{mode} on #{resource[:path]}: #{detail.message}") error.set_backtrace detail.backtrace raise error end end end diff --git a/spec/unit/provider/file/posix_spec.rb b/spec/unit/provider/file/posix_spec.rb index 22d713d24..4de9df7ac 100755 --- a/spec/unit/provider/file/posix_spec.rb +++ b/spec/unit/provider/file/posix_spec.rb @@ -1,232 +1,232 @@ #! /usr/bin/env ruby require 'spec_helper' describe Puppet::Type.type(:file).provider(:posix), :if => Puppet.features.posix? do include PuppetSpec::Files let(:path) { tmpfile('posix_file_spec') } let(:resource) { Puppet::Type.type(:file).new :path => path, :mode => '0777', :provider => described_class.name } let(:provider) { resource.provider } describe "#mode" do it "should return a string with the higher-order bits stripped away" do FileUtils.touch(path) File.chmod(0644, path) - provider.mode.should == '644' + provider.mode.should == '0644' end it "should return absent if the file doesn't exist" do provider.mode.should == :absent end end describe "#mode=" do it "should chmod the file to the specified value" do FileUtils.touch(path) File.chmod(0644, path) provider.mode = '0755' - provider.mode.should == '755' + provider.mode.should == '0755' end it "should pass along any errors encountered" do expect do - provider.mode = '644' + provider.mode = '0644' end.to raise_error(Puppet::Error, /failed to set mode/) end end describe "#uid2name" do it "should return the name of the user identified by the id" do Etc.stubs(:getpwuid).with(501).returns(Struct::Passwd.new('jilluser', nil, 501)) provider.uid2name(501).should == 'jilluser' end it "should return the argument if it's already a name" do provider.uid2name('jilluser').should == 'jilluser' end it "should return nil if the argument is above the maximum uid" do provider.uid2name(Puppet[:maximum_uid] + 1).should == nil end it "should return nil if the user doesn't exist" do Etc.expects(:getpwuid).raises(ArgumentError, "can't find user for 999") provider.uid2name(999).should == nil end end describe "#name2uid" do it "should return the id of the user if it exists" do passwd = Struct::Passwd.new('bobbo', nil, 502) Etc.stubs(:getpwnam).with('bobbo').returns(passwd) Etc.stubs(:getpwuid).with(502).returns(passwd) provider.name2uid('bobbo').should == 502 end it "should return the argument if it's already an id" do provider.name2uid('503').should == 503 end it "should return false if the user doesn't exist" do Etc.stubs(:getpwnam).with('chuck').raises(ArgumentError, "can't find user for chuck") provider.name2uid('chuck').should == false end end describe "#owner" do it "should return the uid of the file owner" do FileUtils.touch(path) owner = Puppet::FileSystem.stat(path).uid provider.owner.should == owner end it "should return absent if the file can't be statted" do provider.owner.should == :absent end it "should warn and return :silly if the value is beyond the maximum uid" do stat = stub('stat', :uid => Puppet[:maximum_uid] + 1) resource.stubs(:stat).returns(stat) provider.owner.should == :silly @logs.should be_any {|log| log.level == :warning and log.message =~ /Apparently using negative UID/} end end describe "#owner=" do it "should set the owner but not the group of the file" do File.expects(:lchown).with(15, nil, resource[:path]) provider.owner = 15 end it "should chown a link if managing links" do resource[:links] = :manage File.expects(:lchown).with(20, nil, resource[:path]) provider.owner = 20 end it "should chown a link target if following links" do resource[:links] = :follow File.expects(:chown).with(20, nil, resource[:path]) provider.owner = 20 end it "should pass along any error encountered setting the owner" do File.expects(:lchown).raises(ArgumentError) expect { provider.owner = 25 }.to raise_error(Puppet::Error, /Failed to set owner to '25'/) end end describe "#gid2name" do it "should return the name of the group identified by the id" do Etc.stubs(:getgrgid).with(501).returns(Struct::Passwd.new('unicorns', nil, nil, 501)) provider.gid2name(501).should == 'unicorns' end it "should return the argument if it's already a name" do provider.gid2name('leprechauns').should == 'leprechauns' end it "should return nil if the argument is above the maximum gid" do provider.gid2name(Puppet[:maximum_uid] + 1).should == nil end it "should return nil if the group doesn't exist" do Etc.expects(:getgrgid).raises(ArgumentError, "can't find group for 999") provider.gid2name(999).should == nil end end describe "#name2gid" do it "should return the id of the group if it exists" do passwd = Struct::Passwd.new('penguins', nil, nil, 502) Etc.stubs(:getgrnam).with('penguins').returns(passwd) Etc.stubs(:getgrgid).with(502).returns(passwd) provider.name2gid('penguins').should == 502 end it "should return the argument if it's already an id" do provider.name2gid('503').should == 503 end it "should return false if the group doesn't exist" do Etc.stubs(:getgrnam).with('wombats').raises(ArgumentError, "can't find group for wombats") provider.name2gid('wombats').should == false end end describe "#group" do it "should return the gid of the file group" do FileUtils.touch(path) group = Puppet::FileSystem.stat(path).gid provider.group.should == group end it "should return absent if the file can't be statted" do provider.group.should == :absent end it "should warn and return :silly if the value is beyond the maximum gid" do stat = stub('stat', :gid => Puppet[:maximum_uid] + 1) resource.stubs(:stat).returns(stat) provider.group.should == :silly @logs.should be_any {|log| log.level == :warning and log.message =~ /Apparently using negative GID/} end end describe "#group=" do it "should set the group but not the owner of the file" do File.expects(:lchown).with(nil, 15, resource[:path]) provider.group = 15 end it "should change the group for a link if managing links" do resource[:links] = :manage File.expects(:lchown).with(nil, 20, resource[:path]) provider.group = 20 end it "should change the group for a link target if following links" do resource[:links] = :follow File.expects(:chown).with(nil, 20, resource[:path]) provider.group = 20 end it "should pass along any error encountered setting the group" do File.expects(:lchown).raises(ArgumentError) expect { provider.group = 25 }.to raise_error(Puppet::Error, /Failed to set group to '25'/) end end describe "when validating" do it "should not perform any validation" do resource.validate end end end