1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from config_common import utils
17 from config_common.rhn_log import log_debug
18
19 import handler_base
20 import os
21 import stat
22 import pwd, grp
23 try:
24 from selinux import lgetfilecon
25 except:
26
29
30 -class Handler(handler_base.HandlerBase):
31 _usage_options = handler_base.HandlerBase._usage_options + " [ files ... ]"
32 _options_table = [
33 handler_base.HandlerBase._option_class(
34 '--verbose',
35 "-v",
36 action="count",
37 help="Increase the amount of output detail.",
38 ),
39 handler_base.HandlerBase._option_class(
40 '--only',
41 "-o",
42 action="count",
43 help="Only show files that differ.",
44 ),
45 ]
46
47
49 log_debug(2)
50 ret = []
51
52
53 status_label = "STATUS"
54 owner_status = "OWNER"
55 group_status = "GROUP"
56 mode_status = "MODE"
57 selinux_status = "SELINUX"
58 file_status = "FILE"
59
60 status_help = "(channel:local)"
61
62 maxlenarr = {
63 'status' : len(status_label),
64 'owner' : max(len(owner_status), len(status_help)),
65 'group' : max(len(group_status), len(status_help)),
66 'mode' : max(len(mode_status), len(status_help)),
67 'selinux' : max(len(selinux_status), len(status_help)),
68 }
69
70
71
72 for file in self.get_valid_files():
73 (src, file_info, dirs_created) = self.repository.get_file_info(file)
74
75 ftype = file_info.get('filetype')
76
77 if not src:
78 continue
79
80 dst = self.get_dest_file(file)
81
82
83 ret_dict = self._process_file(src, dst, file, ftype, file_info)
84
85 if self.options.verbose:
86
87
88 maxlenarr['status'] = max(maxlenarr['status'], len(ret_dict['status']))
89 maxlenarr['owner'] = max(maxlenarr['owner'], len(ret_dict['owner']))
90 maxlenarr['group'] = max(maxlenarr['group'], len(ret_dict['group']))
91 maxlenarr['mode'] = max(maxlenarr['mode'], len(ret_dict['mode']))
92 if len(ret_dict['selinux']) > 0:
93 (src, dst) = ret_dict['selinux'].split('|')
94 maxlenarr['selinux'] = max(maxlenarr['selinux'], len(src), len(dst))
95
96
97 ret.append(ret_dict)
98
99 if self.options.verbose:
100 formatstr = "%-*s"
101 formatstr_nolimit = "%-s"
102
103
104 outstring = "%(status)s %(owner)s %(group)s %(mode)s %(selinux)s %(file)s"
105
106
107 print(outstring % {
108 "status" : formatstr % (maxlenarr['status'], status_label),
109 "owner" : formatstr % (maxlenarr['owner'], owner_status),
110 "group" : formatstr % (maxlenarr['group'], group_status),
111 "mode" : formatstr % (maxlenarr['mode'], mode_status),
112 "selinux" : formatstr % (maxlenarr['selinux'], selinux_status),
113 "file" : formatstr_nolimit % (file_status),
114 })
115
116 print(outstring % {
117 "status" : formatstr % (maxlenarr['status'], ""),
118 "owner" : formatstr % (maxlenarr['owner'], status_help),
119 "group" : formatstr % (maxlenarr['group'], status_help),
120 "mode" : formatstr % (maxlenarr['mode'], status_help),
121 "selinux" : formatstr % (maxlenarr['selinux'], status_help),
122 "file" : ""
123 })
124
125
126 for fdict in ret:
127 src_selinux = dst_selinux = ""
128 if len(fdict['selinux']) > 0:
129 (src_selinux, dst_selinux) = fdict['selinux'].split('|')
130
131 if self.options.only:
132 sum = 0
133 for key in fdict.keys():
134 if key != 'file':
135 sum += len(fdict[key])
136 if sum == 0:
137 continue
138
139 print(outstring % {
140 "status" : formatstr % (maxlenarr['status'], fdict['status']),
141 "owner" : formatstr % (maxlenarr['owner'], fdict['owner']),
142 "group" : formatstr % (maxlenarr['group'], fdict['group']),
143 "mode" : formatstr % (maxlenarr['mode'], fdict['mode']),
144 "selinux" : formatstr % (maxlenarr['selinux'], src_selinux),
145 "file" : formatstr_nolimit % (fdict['file']),
146 })
147 if len(dst_selinux) > 0:
148 print(outstring % {
149 "status" : formatstr % (maxlenarr['status'], ""),
150 "owner" : formatstr % (maxlenarr['owner'], ""),
151 "group" : formatstr % (maxlenarr['group'], ""),
152 "mode" : formatstr % (maxlenarr['mode'], ""),
153 "selinux" : formatstr % (maxlenarr['selinux'], dst_selinux),
154 "file" : "",
155 })
156
157 else:
158 outstring = "%*s %s"
159 maxlen = max([0] + [len(x['status']) for x in ret]) + 1
160 for fdict in ret:
161 if self.options.only and len(fdict['status']) == 0:
162 continue
163 print(outstring % (maxlen, fdict['status'], fdict['file']))
164
166 owner_report = "%s:%s"
167 group_report = "%s:%s"
168 perm_report = "%s:%s"
169 selinux_report = "%s|%s"
170
171 src, dst, file, type, info = args[:5]
172 owner_status = ""
173 group_status = ""
174 perm_status = ""
175 selinux_status = ""
176
177 status = []
178 stat_err = 0
179
180 try:
181 dst_stat = os.lstat(dst)
182 except:
183 stat_err = 1
184 if type != 'symlink':
185 src_user = info['username']
186 if not stat_err:
187
188 dst_uid = dst_stat[stat.ST_UID]
189 try:
190 dst_user = pwd.getpwuid(dst_uid)[0]
191 except KeyError:
192
193 dst_user = "unknown(UID %d)" % (dst_uid,)
194 else:
195 dst_user = "missing"
196
197
198 if src_user == dst_user:
199 owner_status = ""
200 else:
201 owner_status = owner_report % (src_user, dst_user)
202 status.append('user')
203
204 src_group = info['groupname']
205 if not stat_err:
206
207 dst_gid = dst_stat[stat.ST_GID]
208 try:
209 dst_group = grp.getgrgid(dst_gid)[0]
210 except KeyError:
211
212 dst_group = "unknown(GID %d)" % (dst_gid,)
213 else:
214 dst_group = "missing"
215
216
217 if src_group == dst_group:
218 group_status = ""
219 else:
220 group_status = group_report % (src_group, dst_group)
221 status.append('group')
222
223
224 src_perm = str(info['filemode'])
225 if not stat_err:
226
227
228
229
230 dst_perm = str(oct(stat.S_IMODE(dst_stat[stat.ST_MODE])))
231 else:
232 dst_perm = "missing"
233
234
235 if dst_perm[0] == '0':
236 dst_perm = dst_perm[1:]
237
238
239 if src_perm == dst_perm:
240 perm_status = ""
241 else:
242 perm_status = perm_report % (src_perm, dst_perm)
243 status.append('mode')
244
245
246 if 'selinux_ctx' in info:
247 src_selinux = info['selinux_ctx']
248 if src_selinux:
249 if not stat_err:
250 try:
251 dst_selinux = lgetfilecon(dst)[1]
252 except OSError:
253 dst_selinux = ""
254 if dst_selinux == None:
255 dst_selinux = ""
256 else:
257 dst_selinux = "missing"
258
259 if src_selinux == dst_selinux:
260 selinux_status = ""
261 else:
262 selinux_status = selinux_report % (src_selinux, dst_selinux)
263 status.append('selinux')
264
265
266 if stat_err:
267 status = ["missing"]
268 elif type == 'symlink':
269 if not os.path.islink(file):
270 status = ["missing"]
271 elif os.readlink(file) != info['symlink']:
272 status.append('target-link-modified')
273 elif type == 'directory':
274 if not os.path.isdir(file):
275 status = ["missing"]
276
277 elif not os.access(dst, os.R_OK):
278 status = ["missing"]
279
280 else:
281 src_sum = utils.sha256_file(src)
282 dst_sum = utils.sha256_file(dst)
283 if src_sum != dst_sum:
284 status.append('modified')
285
286 return {
287 "status" : ','.join(status),
288 "owner" : owner_status,
289 "group" : group_status,
290 "mode" : perm_status,
291 "selinux" : selinux_status,
292 "file" : file,
293 }
294