diff --git a/lib/puppet/provider/file/posix.rb b/lib/puppet/provider/file/posix.rb index f7b8c9797..7b7336b9d 100644 --- a/lib/puppet/provider/file/posix.rb +++ b/lib/puppet/provider/file/posix.rb @@ -1,97 +1,97 @@ Puppet::Type.type(:file).provide :posix do desc "Uses POSIX functionality to manage file's users and rights." confine :feature => :posix include Puppet::Util::POSIX include Puppet::Util::Warnings require 'etc' def id2name(id) return id.to_s if id.is_a?(Symbol) return nil if id > Puppet[:maximum_uid].to_i begin user = Etc.getpwuid(id) rescue TypeError return nil rescue ArgumentError return nil end if user.uid == "" return nil else return user.name end end def is_owner_insync?(current, should) should.each do |value| if value =~ /^\d+$/ uid = Integer(value) elsif value.is_a?(String) fail "Could not find user #{value}" unless uid = uid(value) else uid = value end return true if uid == current end unless Puppet.features.root? warnonce "Cannot manage ownership unless running as root" return true end false end # Determine if the user is valid, and if so, return the UID def validuser?(value) Integer(value) rescue uid(value) || false end def retrieve(resource) - unless stat = resource.stat(false) + 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 sync(path, links, should) # Set our method appropriately, depending on links. if links == :manage method = :lchown else method = :chown end uid = nil should.each do |user| break if uid = validuser?(user) end raise Puppet::Error, "Could not find user(s) #{should.join(",")}" unless uid begin File.send(method, uid, nil, path) rescue => detail raise Puppet::Error, "Failed to set owner to '#{uid}': #{detail}" end :file_changed end end diff --git a/lib/puppet/provider/file/win32.rb b/lib/puppet/provider/file/win32.rb index 21e7ca974..9423e8f00 100644 --- a/lib/puppet/provider/file/win32.rb +++ b/lib/puppet/provider/file/win32.rb @@ -1,72 +1,72 @@ Puppet::Type.type(:file).provide :microsoft_windows do desc "Uses Microsoft Windows functionality to manage file's users and rights." confine :feature => :microsoft_windows include Puppet::Util::Warnings require 'sys/admin' if Puppet.features.microsoft_windows? def id2name(id) return id.to_s if id.is_a?(Symbol) return nil if id > Puppet[:maximum_uid].to_i # should translate ID numbers to usernames id end def is_owner_insync?(current, should) should.each do |value| if value =~ /^\d+$/ uid = Integer(value) elsif value.is_a?(String) fail "Could not find user #{value}" unless uid = uid(value) else uid = value end return true if uid == current end unless Puppet.features.root? warnonce "Cannot manage ownership unless running as root" return true end false end # Determine if the user is valid, and if so, return the UID def validuser?(value) info "Is '#{value}' a valid user?" return 0 begin number = Integer(value) return number rescue ArgumentError number = nil end (number = uid(value)) && number end def retrieve(resource) - unless stat = resource.stat(false) + 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 sync(path, links, should) info("should set '%s'%%owner to '%s'" % [path, should]) end end diff --git a/lib/puppet/type/file/ctime.rb b/lib/puppet/type/file/ctime.rb index 24b098703..90d95da64 100644 --- a/lib/puppet/type/file/ctime.rb +++ b/lib/puppet/type/file/ctime.rb @@ -1,18 +1,18 @@ module Puppet Puppet::Type.type(:file).newproperty(:ctime) do desc "A read-only state to check the file ctime." def retrieve current_value = :absent - if stat = @resource.stat(false) + if stat = @resource.stat current_value = stat.ctime end current_value end validate do fail "ctime is read-only" end end end diff --git a/lib/puppet/type/file/ensure.rb b/lib/puppet/type/file/ensure.rb index 99652ecc6..0f065da14 100755 --- a/lib/puppet/type/file/ensure.rb +++ b/lib/puppet/type/file/ensure.rb @@ -1,164 +1,164 @@ module Puppet Puppet::Type.type(:file).ensurable do require 'etc' desc "Whether to create files that don't currently exist. Possible values are *absent*, *present*, *file*, and *directory*. Specifying `present` will match any form of file existence, and if the file is missing will create an empty file. Specifying `absent` will delete the file (and directory if recurse => true). Anything other than those values will create a symlink. In the interest of readability and clarity, you should use `ensure => link` and explicitly specify a target; however, if a `target` attribute isn't provided, the value of the `ensure` attribute will be used as the symlink target: # (Useful on Solaris) # Less maintainable: file { \"/etc/inetd.conf\": ensure => \"/etc/inet/inetd.conf\", } # More maintainable: file { \"/etc/inetd.conf\": ensure => link, target => \"/etc/inet/inetd.conf\", } These two declarations are equivalent." # Most 'ensure' properties have a default, but with files we, um, don't. nodefault newvalue(:absent) do File.unlink(@resource[:path]) end aliasvalue(:false, :absent) newvalue(:file, :event => :file_created) do # Make sure we're not managing the content some other way if property = @resource.property(:content) property.sync else @resource.write(:ensure) mode = @resource.should(:mode) end end #aliasvalue(:present, :file) newvalue(:present, :event => :file_created) do # Make a file if they want something, but this will match almost # anything. set_file end newvalue(:directory, :event => :directory_created) do mode = @resource.should(:mode) parent = File.dirname(@resource[:path]) unless FileTest.exists? parent raise Puppet::Error, "Cannot create #{@resource[:path]}; parent directory #{parent} does not exist" end if mode Puppet::Util.withumask(000) do Dir.mkdir(@resource[:path], mode.to_i(8)) end else Dir.mkdir(@resource[:path]) end @resource.send(:property_fix) return :directory_created end newvalue(:link, :event => :link_created) do fail "Cannot create a symlink without a target" unless property = resource.property(:target) property.retrieve property.mklink end # Symlinks. newvalue(/./) do # This code never gets executed. We need the regex to support # specifying it, but the work is done in the 'symlink' code block. end munge do |value| value = super(value) value,resource[:target] = :link,value unless value.is_a? Symbol resource[:links] = :manage if value == :link and resource[:links] != :follow value end def change_to_s(currentvalue, newvalue) return super unless newvalue.to_s == "file" return super unless property = @resource.property(:content) # We know that content is out of sync if we're here, because # it's essentially equivalent to 'ensure' in the transaction. if source = @resource.parameter(:source) should = source.checksum else should = property.should end if should == :absent is = property.retrieve else is = :absent end property.change_to_s(is, should) end # Check that we can actually create anything def check basedir = File.dirname(@resource[:path]) if ! FileTest.exists?(basedir) raise Puppet::Error, "Can not create #{@resource.title}; parent directory does not exist" elsif ! FileTest.directory?(basedir) raise Puppet::Error, "Can not create #{@resource.title}; #{dirname} is not a directory" end end # We have to treat :present specially, because it works with any # type of file. def insync?(currentvalue) unless currentvalue == :absent or resource.replace? return true end if self.should == :present return !(currentvalue.nil? or currentvalue == :absent) else return super(currentvalue) end end def retrieve - if stat = @resource.stat(false) + if stat = @resource.stat return stat.ftype.intern else if self.should == :false return :false else return :absent end end end def sync @resource.remove_existing(self.should) if self.should == :absent return :file_removed end event = super event end end end diff --git a/lib/puppet/type/file/group.rb b/lib/puppet/type/file/group.rb index 5ed5166bc..4d1f2f4e6 100755 --- a/lib/puppet/type/file/group.rb +++ b/lib/puppet/type/file/group.rb @@ -1,113 +1,113 @@ require 'puppet/util/posix' # Manage file group ownership. module Puppet Puppet::Type.type(:file).newproperty(:group) do include Puppet::Util::POSIX require 'etc' desc "Which group should own the file. Argument can be either group name or group ID." @event = :file_changed validate do |group| raise(Puppet::Error, "Invalid group name '#{group.inspect}'") unless group and group != "" end def id2name(id) return id.to_s if id.is_a?(Symbol) return nil if id > Puppet[:maximum_uid].to_i begin group = Etc.getgrgid(id) rescue ArgumentError return nil end if group.gid == "" return nil else return group.name end end # We want to print names, not numbers def is_to_s(currentvalue) if currentvalue.is_a? Integer id2name(currentvalue) || currentvalue else return currentvalue.to_s end end def should_to_s(newvalue = @should) if newvalue.is_a? Integer id2name(newvalue) || newvalue else return newvalue.to_s end end def insync?(current) @should.each do |value| if value =~ /^\d+$/ gid = Integer(value) elsif value.is_a?(String) fail "Could not find group #{value}" unless gid = gid(value) else gid = value end return true if gid == current end false end def retrieve - return :absent unless stat = resource.stat(false) + 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 # Determine if the group is valid, and if so, return the GID def validgroup?(value) Integer(value) rescue gid(value) || false end # Normal users will only be able to manage certain groups. Right now, # we'll just let it fail, but we should probably set things up so # that users get warned if they try to change to an unacceptable group. def sync # Set our method appropriately, depending on links. if resource[:links] == :manage method = :lchown else method = :chown end gid = nil @should.each do |group| break if gid = validgroup?(group) end raise Puppet::Error, "Could not find group(s) #{@should.join(",")}" unless gid begin # set owner to nil so it's ignored File.send(method, nil, gid, resource[:path]) rescue => detail error = Puppet::Error.new( "failed to chgrp #{resource[:path]} to #{gid}: #{detail.message}") raise error end :file_changed end end end diff --git a/lib/puppet/type/file/mode.rb b/lib/puppet/type/file/mode.rb index 2acd8b359..9f58e6fb0 100755 --- a/lib/puppet/type/file/mode.rb +++ b/lib/puppet/type/file/mode.rb @@ -1,90 +1,90 @@ # Manage file modes. This state should support different formats # for specification (e.g., u+rwx, or -0011), but for now only supports # specifying the full mode. 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. 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 entries in a directory, and search/traverse allows you to access (read/write/execute) those entries.) Because of this feature, you can recursively make a directory and all of the files in it world-readable by setting e.g.: file { '/some/dir': mode => 644, recurse => true, } 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 munge do |should| if should.is_a?(String) unless should =~ /^[0-7]+$/ raise Puppet::Error, "File modes can only be octal numbers, not #{should.inspect}" end should.to_i(8).to_s(8) else should.to_s(8) 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. def dirmask(value) if FileTest.directory?(@resource[:path]) value = value.to_i(8) value |= 0100 if value & 0400 != 0 value |= 010 if value & 040 != 0 value |= 01 if value & 04 != 0 value = value.to_s(8) end value end def insync?(currentvalue) if stat = @resource.stat and stat.ftype == "link" and @resource[:links] != :follow self.debug "Not managing symlink mode" return true else return super(currentvalue) end end def retrieve # If we're not following links and we're a link, then we just turn # off mode management entirely. - if stat = @resource.stat(false) + if stat = @resource.stat unless defined?(@fixed) @should &&= @should.collect { |s| self.dirmask(s) } end return (stat.mode & 007777).to_s(8) else return :absent end end def sync mode = self.should begin File.chmod(mode.to_i(8), @resource[:path]) rescue => detail error = Puppet::Error.new("failed to chmod #{@resource[:path]}: #{detail.message}") error.set_backtrace detail.backtrace raise error end :file_changed end end end diff --git a/lib/puppet/type/file/mtime.rb b/lib/puppet/type/file/mtime.rb index 8ca7ed0d6..5952b4b84 100644 --- a/lib/puppet/type/file/mtime.rb +++ b/lib/puppet/type/file/mtime.rb @@ -1,17 +1,17 @@ module Puppet Puppet::Type.type(:file).newproperty(:mtime) do desc "A read-only state to check the file mtime." def retrieve current_value = :absent - if stat = @resource.stat(false) + if stat = @resource.stat current_value = stat.mtime end current_value end validate do fail "mtime is read-only" end end end diff --git a/lib/puppet/type/file/selcontext.rb b/lib/puppet/type/file/selcontext.rb index ea385eec0..1b1a77245 100644 --- a/lib/puppet/type/file/selcontext.rb +++ b/lib/puppet/type/file/selcontext.rb @@ -1,119 +1,119 @@ # Manage SELinux context of files. # # This code actually manages three pieces of data in the context. # # [root@delenn files]# ls -dZ / # drwxr-xr-x root root system_u:object_r:root_t / # # The context of '/' here is 'system_u:object_r:root_t'. This is # three seperate fields: # # system_u is the user context # object_r is the role context # root_t is the type context # # All three of these fields are returned in a single string by the # output of the stat command, but set individually with the chcon # command. This allows the user to specify a subset of the three # values while leaving the others alone. # # See http://www.nsa.gov/selinux/ for complete docs on SELinux. module Puppet require 'puppet/util/selinux' class SELFileContext < Puppet::Property include Puppet::Util::SELinux def retrieve - return :absent unless @resource.stat(false) + return :absent unless @resource.stat context = self.get_selinux_current_context(@resource[:path]) parse_selinux_context(name, context) end def retrieve_default_context(property) if @resource[:selinux_ignore_defaults] == :true return nil end unless context = self.get_selinux_default_context(@resource[:path]) return nil end property_default = self.parse_selinux_context(property, context) self.debug "Found #{property} default '#{property_default}' for #{@resource[:path]}" if not property_default.nil? property_default end def insync?(value) if not selinux_support? debug("SELinux bindings not found. Ignoring parameter.") return true end super end def sync self.set_selinux_context(@resource[:path], @should, name) :file_changed end end Puppet::Type.type(:file).newparam(:selinux_ignore_defaults) do desc "If this is set then Puppet will not ask SELinux (via matchpathcon) to supply defaults for the SELinux attributes (seluser, selrole, seltype, and selrange). In general, you should leave this set at its default and only set it to true when you need Puppet to not try to fix SELinux labels automatically." newvalues(:true, :false) defaultto :false end Puppet::Type.type(:file).newproperty(:seluser, :parent => Puppet::SELFileContext) do desc "What the SELinux user component of the context of the file should be. Any valid SELinux user component is accepted. For example `user_u`. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled." @event = :file_changed defaultto { self.retrieve_default_context(:seluser) } end Puppet::Type.type(:file).newproperty(:selrole, :parent => Puppet::SELFileContext) do desc "What the SELinux role component of the context of the file should be. Any valid SELinux role component is accepted. For example `role_r`. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled." @event = :file_changed defaultto { self.retrieve_default_context(:selrole) } end Puppet::Type.type(:file).newproperty(:seltype, :parent => Puppet::SELFileContext) do desc "What the SELinux type component of the context of the file should be. Any valid SELinux type component is accepted. For example `tmp_t`. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled." @event = :file_changed defaultto { self.retrieve_default_context(:seltype) } end Puppet::Type.type(:file).newproperty(:selrange, :parent => Puppet::SELFileContext) do desc "What the SELinux range component of the context of the file should be. Any valid SELinux range component is accepted. For example `s0` or `SystemHigh`. If not specified it defaults to the value returned by matchpathcon for the file, if any exists. Only valid on systems with SELinux support enabled and that have support for MCS (Multi-Category Security)." @event = :file_changed defaultto { self.retrieve_default_context(:selrange) } end end diff --git a/lib/puppet/type/file/type.rb b/lib/puppet/type/file/type.rb index 4da54e2cb..864d3b1a4 100755 --- a/lib/puppet/type/file/type.rb +++ b/lib/puppet/type/file/type.rb @@ -1,19 +1,19 @@ module Puppet Puppet::Type.type(:file).newproperty(:type) do require 'etc' desc "A read-only state to check the file type." def retrieve current_value = :absent - if stat = @resource.stat(false) + if stat = @resource.stat current_value = stat.ftype end current_value end validate do fail "type is read-only" end end end