Repository navigation
Expand file tree
/
Copy pathfile_access_control.rb
More file actions
140 lines (120 loc) · 4.4 KB
/
Copy pathfile_access_control.rb
File metadata and controls
140 lines (120 loc) · 4.4 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#
# Author:: Adam Jacob (<adam@opscode.com>)
# Author:: Daniel DeLeo (<dan@opscode.com>)
# Copyright:: Copyright (c) 2008, 2010 Opscode, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'chef/log'
class Chef
# == Chef::FileAccessControl
# FileAccessControl objects set the owner, group and mode of +file+ to
# the values specified by a value object, usually a Chef::Resource.
class FileAccessControl
UINT = (1 << 32)
UID_MAX = (1 << 31)
attr_reader :resource
attr_reader :file
# FileAccessControl objects set the owner, group and mode of +file+ to
# the values specified by +resource+. +file+ is completely independent
# of any file or path attribute on +resource+, so it is possible to set
# access control settings on a tempfile (for example).
# === Arguments:
# resource: probably a Chef::Resource::File object (or subclass), but
# this is not required. Must respond to +owner+, +group+,
# and +mode+
# file: The file whose access control settings you wish to modify,
# given as a String.
def initialize(resource, file)
@resource, @file = resource, file
@modified = false
end
def modified?
@modified
end
def set_all
set_owner
set_group
set_mode
end
# Workaround the fact that Ruby's Etc module doesn't believe in negative
# uids, so negative uids show up as the diminished radix complement of
# a uint. For example, a uid of -2 is reported as 4294967294
def dimished_radix_complement(int)
if int > UID_MAX
int - UINT
else
int
end
end
def target_uid
return nil if resource.owner.nil?
if resource.owner.kind_of?(String)
dimished_radix_complement( Etc.getpwnam(resource.owner).uid )
elsif resource.owner.kind_of?(Integer)
resource.owner
else
Chef::Log.error("The `owner` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{resource.owner.inspect} to uid, owner must be a string or integer"
end
rescue ArgumentError
raise Chef::Exceptions::UserIDNotFound, "cannot determine user id for '#{resource.owner}', does the user exist on this system?"
end
def set_owner
if (uid = target_uid) && (uid != stat.uid)
Chef::Log.debug("setting owner on #{file} to #{uid}")
File.chown(uid, nil, file)
modified
end
end
def target_gid
return nil if resource.group.nil?
if resource.group.kind_of?(String)
dimished_radix_complement( Etc.getgrnam(resource.group).gid )
elsif resource.group.kind_of?(Integer)
resource.group
else
Chef::Log.error("The `group` parameter of the #@resource resource is set to an invalid value (#{resource.owner.inspect})")
raise ArgumentError, "cannot resolve #{resource.group.inspect} to gid, group must be a string or integer"
end
rescue ArgumentError
raise Chef::Exceptions::GroupIDNotFound, "cannot determine group id for '#{resource.group}', does the group exist on this system?"
end
def set_group
if (gid = target_gid) && (gid != stat.gid)
Chef::Log.debug("setting group on #{file} to #{gid}")
File.chown(nil, gid, file)
modified
end
end
def target_mode
return nil if resource.mode.nil?
(resource.mode.respond_to?(:oct) ? resource.mode.oct : resource.mode.to_i) & 007777
end
def set_mode
if (mode = target_mode) && (mode != (stat.mode & 007777))
Chef::Log.debug("setting mode on #{file} to #{mode.to_s(8)}")
File.chmod(target_mode, file)
modified
end
end
def stat
@stat ||= ::File.stat(file)
end
private
def modified
@modified = true
end
end
end