summaryrefslogtreecommitdiffstats
path: root/lib/puppet/type/file/target.rb
blob: ab7b847a76de1792416ee5c0c9f6b5176c2cc582 (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
module Puppet
    Puppet::Type.type(:file).newproperty(:target) do
        desc "The target for creating a link.  Currently, symlinks are the
            only type supported."

        newvalue(:notlink) do
            # We do nothing if the value is absent
            return :nochange
        end

        # Anything else, basically
        newvalue(/./) do
            @resource[:ensure] = :link if ! @resource.should(:ensure)

            # Only call mklink if ensure() didn't call us in the first place.
            currentensure  = @resource.property(:ensure).retrieve
            mklink() if @resource.property(:ensure).insync?(currentensure)
        end

        # Create our link.
        def mklink
            raise Puppet::Error, "Cannot symlink on Microsoft Windows" if Puppet.features.microsoft_windows?

            target = self.should

            # Clean up any existing objects.  The argument is just for logging,
            # it doesn't determine what's removed.
            @resource.remove_existing(target)

            raise Puppet::Error, "Could not remove existing file" if FileTest.exists?(@resource[:path])

            Dir.chdir(File.dirname(@resource[:path])) do
                Puppet::Util::SUIDManager.asuser(@resource.asuser()) do
                    mode = @resource.should(:mode)
                    if mode
                        Puppet::Util.withumask(000) do
                            File.symlink(target, @resource[:path])
                        end
                    else
                        File.symlink(target, @resource[:path])
                    end
                end

                @resource.send(:property_fix)

                :link_created
            end
        end

        def insync?(currentvalue)
            if [:nochange, :notlink].include?(self.should) or @resource.recurse?
                return true
            elsif ! @resource.replace? and File.exists?(@resource[:path])
                return true
            else
                return super(currentvalue)
            end
        end


        def retrieve
            if stat = @resource.stat
                if stat.ftype == "link"
                    return File.readlink(@resource[:path])
                else
                    return :notlink
                end
            else
                return :absent
            end
        end
    end
end