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
120
121
122
123
124
|
# 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
# Our modes are octal, so make sure they print correctly. Other
# valid values are symbols, basically
def is_to_s(currentvalue)
case currentvalue
when Integer
return "%o" % currentvalue
when Symbol
return currentvalue
else
raise Puppet::DevError, "Invalid current value for mode: #{currentvalue.inspect}"
end
end
def should_to_s(newvalue = @should)
case newvalue
when Integer
return "%o" % newvalue
when Symbol
return newvalue
else
raise Puppet::DevError, "Invalid 'should' value for mode: #{newvalue.inspect}"
end
end
munge do |should|
# this is pretty hackish, but i need to make sure the number is in
# octal, yet the number can only be specified as a string right now
value = should
if value.is_a?(String)
unless value =~ /^\d+$/
raise Puppet::Error, "File modes can only be numbers, not #{value.inspect}"
end
# Make sure our number looks like octal.
unless value =~ /^0/
value = "0#{value}"
end
old = value
begin
value = Integer(value)
rescue ArgumentError => detail
raise Puppet::DevError, "Could not convert #{old.inspect} to integer"
end
end
return value
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 |= 0100 if value & 0400 != 0
value |= 010 if value & 040 != 0
value |= 01 if value & 04 != 0
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)
unless defined?(@fixed)
@should &&= @should.collect { |s| self.dirmask(s) }
end
return stat.mode & 007777
else
return :absent
end
end
def sync
mode = self.should
begin
File.chmod(mode, @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
|