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