summaryrefslogtreecommitdiffstats
path: root/lib/puppet/util/posix.rb
blob: d7e3bb8b2bbeab7e5422a19f1a44639522bc773f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Utility methods for interacting with POSIX objects; mostly user and group
module Puppet::Util::POSIX

    # Retrieve a field from a POSIX Etc object.  The id can be either an integer
    # or a name.  This only works for users and groups.  It's also broken on
    # some platforms, unfortunately.
    def old_get_posix_field(space, field, id)
        unless id
            raise ArgumentError, "Did not get id"
        end
        if id =~ /^\d+$/
            id = Integer(id)
        end
        prefix = "get" + space.to_s
        if id.is_a?(Integer)
            if id > 1000000
                Puppet.err "Tried to get %s field for silly id %s" % [field, id]
                return nil
            end
            method = (prefix + idfield(space).to_s).intern
        else
            method = (prefix + "nam").intern
        end

        begin
            return Etc.send(method, id).send(field)
        rescue ArgumentError => detail
            # ignore it; we couldn't find the object
            return nil
        end
    end

    # A degenerate method of retrieving name/id mappings.  The job of this method is
    # to find a specific entry and then return a given field from that entry.
    def get_posix_field(type, field, id)
        idmethod = idfield(type)
        integer = false
        if id =~ /^\d+$/
            id = Integer(id)
        end
        if id.is_a?(Integer)
            integer = true
            if id > 1000000
                Puppet.err "Tried to get %s field for silly id %s" % [field, id]
                return nil
            end
        end

        Etc.send(type) do |object|
            if integer and object.send(idmethod) == id
                return object.send(field)
            elsif object.name == id
                return object.send(field)
            end
        end
        return nil
    end
    
    # Look in memory for an already-managed type and use its info if available.
    # Currently unused.
    def get_provider_value(type, field, id)
        unless typeklass = Puppet::Type.type(type)
            raise ArgumentError, "Invalid type %s" % type
        end
        
        id = id.to_s
        
        chkfield = idfield(type)
        obj = typeklass.find { |obj|
            if id =~ /^\d+$/
                obj.should(chkfield).to_s == id ||
                    obj.provider.send(chkfield) == id
            else 
                obj[:name] == id
            end                    
        }
        
        return nil unless obj
        
        if obj.provider
            begin
                val = obj.provider.send(field)
                if val == :absent
                    return nil
                else
                    return val
                end
            rescue => detail
                if Puppet[:trace]
                    puts detail.backtrace
                    Puppet.err detail
                    return nil
                end
            end
        end
    end
    
    # Determine what the field name is for users and groups.
    def idfield(space)
        case Puppet::Util.symbolize(space)
        when :gr, :group: return :gid
        when :pw, :user, :passwd: return :uid
        else
            raise ArgumentError.new("Can only handle users and groups")
        end
    end
    
    # Get the GID of a given group, provided either a GID or a name
    def gid(group)
        get_posix_field(:group, :gid, group)
    end

    # Get the UID of a given user, whether a UID or name is provided
    def uid(user)
        get_posix_field(:passwd, :uid, user)
    end
end

# $Id$