Update valied license list
[platform/upstream/rpmlint.git] / FilesCheck.py
1 # -*- coding: utf-8 -*-
2 #############################################################################
3 # File          : FilesCheck.py
4 # Package       : rpmlint
5 # Author        : Frederic Lepied
6 # Created on    : Mon Oct  4 19:32:49 1999
7 # Version       : $Id: FilesCheck.py 1894 2011-11-24 21:56:18Z scop $
8 # Purpose       : test various aspects on files: locations, owner, groups,
9 #                 permission, setuid, setgid...
10 #############################################################################
11
12 from datetime import datetime
13 import commands
14 import os
15 import re
16 import stat
17 import string
18
19 import rpm
20
21 from Filter import addDetails, printError, printWarning
22 from Pkg import catcmd, is_utf8, is_utf8_str
23 import AbstractCheck
24 import Config
25
26
27 # must be kept in sync with the filesystem package
28 STANDARD_DIRS = (
29     '/',
30     '/bin',
31     '/boot',
32     '/dev',
33     '/etc',
34     '/etc/X11',
35     '/etc/aliases.d',
36     '/etc/cron.d',
37     '/etc/cron.daily',
38     '/etc/cron.hourly',
39     '/etc/cron.monthly',
40     '/etc/cron.weekly',
41     '/etc/cups',
42     '/etc/default',
43     '/etc/init.d',
44     '/etc/init.d/boot.d',
45     '/etc/init.d/rc0.d',
46     '/etc/init.d/rc1.d',
47     '/etc/init.d/rc2.d',
48     '/etc/init.d/rc3.d',
49     '/etc/init.d/rc4.d',
50     '/etc/init.d/rc5.d',
51     '/etc/init.d/rc6.d',
52     '/etc/init.d/rcS.d',
53     '/etc/java',
54     '/etc/ld.so.conf.d',
55     '/etc/logrotate.d',
56     '/etc/news',
57     '/etc/opt',
58     '/etc/permissions.d',
59     '/etc/ppp',
60     '/etc/ppp/ip-down.d',
61     '/etc/ppp/ip-up.d',
62     '/etc/profile.d',
63     '/etc/rc.d',
64     '/etc/skel',
65     '/etc/susehelp.d',
66     '/etc/susehelp.d/htdig',
67     '/etc/sysconfig',
68     '/etc/sysconfig/SuSEfirewall2.d',
69     '/etc/sysconfig/SuSEfirewall2.d/services',
70     '/etc/sysconfig/network',
71     '/etc/sysconfig/network/if-down.d',
72     '/etc/sysconfig/network/if-up.d',
73     '/etc/sysconfig/network/providers',
74     '/etc/sysconfig/network/scripts',
75     '/etc/sysconfig/scripts',
76     '/etc/uucp',
77     '/etc/xdg',
78     '/etc/xdg/autostart',
79     '/etc/xinetd.d',
80     '/home',
81     '/lib',
82     '/lib/YaST',
83     '/lib/firmware',
84     '/lib/lsb',
85     '/lib/modules',
86     '/lib64',
87     '/lib64/YaST',
88     '/lib64/firmware',
89     '/lib64/lsb',
90     '/lib64/modules',
91     '/media',
92     '/media/cdrom',
93     '/media/floppy',
94     '/mnt',
95     '/opt',
96     '/proc',
97     '/root',
98     '/root/.gnupg',
99     '/root/bin',
100     '/sbin',
101     '/srv',
102     '/srv/ftp',
103     '/srv/www',
104     '/srv/www/cgi-bin',
105     '/srv/www/htdocs',
106     '/sys',
107     '/tmp',
108     '/tmp/.ICE-unix',
109     '/tmp/.X11-unix',
110     '/usr',
111     '/usr/X11R6',
112     '/usr/X11R6/bin',
113     '/usr/X11R6/lib',
114     '/usr/bin',
115     '/usr/games',
116     '/usr/i586-suse-linux',
117     '/usr/i586-suse-linux/bin',
118     '/usr/i586-suse-linux/include',
119     '/usr/i586-suse-linux/lib',
120     '/usr/include',
121     '/usr/include/X11',
122     '/usr/lib',
123     '/usr/lib/X11',
124     '/usr/lib/browser-plugins',
125     '/usr/lib/lsb',
126     '/usr/lib/news',
127     '/usr/lib/pkgconfig',
128     '/usr/lib64',
129     '/usr/lib64/X11',
130     '/usr/lib64/browser-plugins',
131     '/usr/lib64/lsb',
132     '/usr/lib64/news',
133     '/usr/lib64/pkgconfig',
134     '/usr/local',
135     '/usr/local/bin',
136     '/usr/local/games',
137     '/usr/local/include',
138     '/usr/local/lib',
139     '/usr/local/lib64',
140     '/usr/local/man',
141     '/usr/local/man/man1',
142     '/usr/local/man/man2',
143     '/usr/local/man/man3',
144     '/usr/local/man/man4',
145     '/usr/local/man/man5',
146     '/usr/local/man/man6',
147     '/usr/local/man/man7',
148     '/usr/local/man/man8',
149     '/usr/local/man/man9',
150     '/usr/local/man/mann',
151     '/usr/local/sbin',
152     '/usr/local/share',
153     '/usr/local/src',
154     '/usr/sbin',
155     '/usr/share',
156     '/usr/share/applications',
157     '/usr/share/dict',
158     '/usr/share/doc',
159     '/usr/share/doc/packages',
160     '/usr/share/fonts',
161     '/usr/share/games',
162     '/usr/share/icons',
163     '/usr/share/info',
164     '/usr/share/java',
165     '/usr/share/locale',
166     '/usr/share/locale/aa',
167     '/usr/share/locale/aa/LC_MESSAGES',
168     '/usr/share/locale/af',
169     '/usr/share/locale/af/LC_MESSAGES',
170     '/usr/share/locale/am',
171     '/usr/share/locale/am/LC_MESSAGES',
172     '/usr/share/locale/ang',
173     '/usr/share/locale/ang/LC_MESSAGES',
174     '/usr/share/locale/ar',
175     '/usr/share/locale/ar/LC_MESSAGES',
176     '/usr/share/locale/as',
177     '/usr/share/locale/as/LC_MESSAGES',
178     '/usr/share/locale/az',
179     '/usr/share/locale/az/LC_MESSAGES',
180     '/usr/share/locale/az_IR',
181     '/usr/share/locale/az_IR/LC_MESSAGES',
182     '/usr/share/locale/be',
183     '/usr/share/locale/be/LC_MESSAGES',
184     '/usr/share/locale/be@latin',
185     '/usr/share/locale/be@latin/LC_MESSAGES',
186     '/usr/share/locale/bg',
187     '/usr/share/locale/bg/LC_MESSAGES',
188     '/usr/share/locale/bn',
189     '/usr/share/locale/bn/LC_MESSAGES',
190     '/usr/share/locale/bn_IN',
191     '/usr/share/locale/bn_IN/LC_MESSAGES',
192     '/usr/share/locale/bo',
193     '/usr/share/locale/bo/LC_MESSAGES',
194     '/usr/share/locale/br',
195     '/usr/share/locale/br/LC_MESSAGES',
196     '/usr/share/locale/bs',
197     '/usr/share/locale/bs/LC_MESSAGES',
198     '/usr/share/locale/byn',
199     '/usr/share/locale/byn/LC_MESSAGES',
200     '/usr/share/locale/ca',
201     '/usr/share/locale/ca/LC_MESSAGES',
202     '/usr/share/locale/ca@valencia',
203     '/usr/share/locale/ca@valencia/LC_MESSAGES',
204     '/usr/share/locale/cs',
205     '/usr/share/locale/cs/LC_MESSAGES',
206     '/usr/share/locale/cs_CZ',
207     '/usr/share/locale/cs_CZ/LC_MESSAGES',
208     '/usr/share/locale/cy',
209     '/usr/share/locale/cy/LC_MESSAGES',
210     '/usr/share/locale/da',
211     '/usr/share/locale/da/LC_MESSAGES',
212     '/usr/share/locale/de',
213     '/usr/share/locale/de/LC_MESSAGES',
214     '/usr/share/locale/de_AT',
215     '/usr/share/locale/de_AT/LC_MESSAGES',
216     '/usr/share/locale/de_CH',
217     '/usr/share/locale/de_CH/LC_MESSAGES',
218     '/usr/share/locale/de_DE',
219     '/usr/share/locale/de_DE/LC_MESSAGES',
220     '/usr/share/locale/dv',
221     '/usr/share/locale/dv/LC_MESSAGES',
222     '/usr/share/locale/dz',
223     '/usr/share/locale/dz/LC_MESSAGES',
224     '/usr/share/locale/ee',
225     '/usr/share/locale/ee/LC_MESSAGES',
226     '/usr/share/locale/el',
227     '/usr/share/locale/el/LC_MESSAGES',
228     '/usr/share/locale/el_GR',
229     '/usr/share/locale/el_GR/LC_MESSAGES',
230     '/usr/share/locale/en',
231     '/usr/share/locale/en/LC_MESSAGES',
232     '/usr/share/locale/en@IPA',
233     '/usr/share/locale/en@IPA/LC_MESSAGES',
234     '/usr/share/locale/en@boldquot',
235     '/usr/share/locale/en@boldquot/LC_MESSAGES',
236     '/usr/share/locale/en@quot',
237     '/usr/share/locale/en@quot/LC_MESSAGES',
238     '/usr/share/locale/en_AU',
239     '/usr/share/locale/en_AU/LC_MESSAGES',
240     '/usr/share/locale/en_CA',
241     '/usr/share/locale/en_CA/LC_MESSAGES',
242     '/usr/share/locale/en_GB',
243     '/usr/share/locale/en_GB/LC_MESSAGES',
244     '/usr/share/locale/en_US',
245     '/usr/share/locale/en_US/LC_MESSAGES',
246     '/usr/share/locale/eo',
247     '/usr/share/locale/eo/LC_MESSAGES',
248     '/usr/share/locale/es',
249     '/usr/share/locale/es/LC_MESSAGES',
250     '/usr/share/locale/es_AR',
251     '/usr/share/locale/es_AR/LC_MESSAGES',
252     '/usr/share/locale/es_CL',
253     '/usr/share/locale/es_CL/LC_MESSAGES',
254     '/usr/share/locale/es_CO',
255     '/usr/share/locale/es_CO/LC_MESSAGES',
256     '/usr/share/locale/es_CR',
257     '/usr/share/locale/es_CR/LC_MESSAGES',
258     '/usr/share/locale/es_DO',
259     '/usr/share/locale/es_DO/LC_MESSAGES',
260     '/usr/share/locale/es_EC',
261     '/usr/share/locale/es_EC/LC_MESSAGES',
262     '/usr/share/locale/es_ES',
263     '/usr/share/locale/es_ES/LC_MESSAGES',
264     '/usr/share/locale/es_GT',
265     '/usr/share/locale/es_GT/LC_MESSAGES',
266     '/usr/share/locale/es_HN',
267     '/usr/share/locale/es_HN/LC_MESSAGES',
268     '/usr/share/locale/es_MX',
269     '/usr/share/locale/es_MX/LC_MESSAGES',
270     '/usr/share/locale/es_NI',
271     '/usr/share/locale/es_NI/LC_MESSAGES',
272     '/usr/share/locale/es_PA',
273     '/usr/share/locale/es_PA/LC_MESSAGES',
274     '/usr/share/locale/es_PE',
275     '/usr/share/locale/es_PE/LC_MESSAGES',
276     '/usr/share/locale/es_PR',
277     '/usr/share/locale/es_PR/LC_MESSAGES',
278     '/usr/share/locale/es_SV',
279     '/usr/share/locale/es_SV/LC_MESSAGES',
280     '/usr/share/locale/es_UY',
281     '/usr/share/locale/es_UY/LC_MESSAGES',
282     '/usr/share/locale/es_VE',
283     '/usr/share/locale/es_VE/LC_MESSAGES',
284     '/usr/share/locale/et',
285     '/usr/share/locale/et/LC_MESSAGES',
286     '/usr/share/locale/et_EE',
287     '/usr/share/locale/et_EE/LC_MESSAGES',
288     '/usr/share/locale/eu',
289     '/usr/share/locale/eu/LC_MESSAGES',
290     '/usr/share/locale/eu_ES',
291     '/usr/share/locale/eu_ES/LC_MESSAGES',
292     '/usr/share/locale/fa',
293     '/usr/share/locale/fa/LC_MESSAGES',
294     '/usr/share/locale/fi',
295     '/usr/share/locale/fi/LC_MESSAGES',
296     '/usr/share/locale/fi_FI',
297     '/usr/share/locale/fi_FI/LC_MESSAGES',
298     '/usr/share/locale/fo',
299     '/usr/share/locale/fo/LC_MESSAGES',
300     '/usr/share/locale/fr',
301     '/usr/share/locale/fr/LC_MESSAGES',
302     '/usr/share/locale/fr_CA',
303     '/usr/share/locale/fr_CA/LC_MESSAGES',
304     '/usr/share/locale/fr_CH',
305     '/usr/share/locale/fr_CH/LC_MESSAGES',
306     '/usr/share/locale/fr_FR',
307     '/usr/share/locale/fr_FR/LC_MESSAGES',
308     '/usr/share/locale/fy',
309     '/usr/share/locale/fy/LC_MESSAGES',
310     '/usr/share/locale/ga',
311     '/usr/share/locale/ga/LC_MESSAGES',
312     '/usr/share/locale/gd',
313     '/usr/share/locale/gd/LC_MESSAGES',
314     '/usr/share/locale/gez',
315     '/usr/share/locale/gez/LC_MESSAGES',
316     '/usr/share/locale/gl',
317     '/usr/share/locale/gl/LC_MESSAGES',
318     '/usr/share/locale/gn',
319     '/usr/share/locale/gn/LC_MESSAGES',
320     '/usr/share/locale/gr',
321     '/usr/share/locale/gr/LC_MESSAGES',
322     '/usr/share/locale/gu',
323     '/usr/share/locale/gu/LC_MESSAGES',
324     '/usr/share/locale/gv',
325     '/usr/share/locale/gv/LC_MESSAGES',
326     '/usr/share/locale/haw',
327     '/usr/share/locale/haw/LC_MESSAGES',
328     '/usr/share/locale/he',
329     '/usr/share/locale/he/LC_MESSAGES',
330     '/usr/share/locale/hi',
331     '/usr/share/locale/hi/LC_MESSAGES',
332     '/usr/share/locale/hr',
333     '/usr/share/locale/hr/LC_MESSAGES',
334     '/usr/share/locale/hu',
335     '/usr/share/locale/hu/LC_MESSAGES',
336     '/usr/share/locale/hy',
337     '/usr/share/locale/hy/LC_MESSAGES',
338     '/usr/share/locale/ia',
339     '/usr/share/locale/ia/LC_MESSAGES',
340     '/usr/share/locale/id',
341     '/usr/share/locale/id/LC_MESSAGES',
342     '/usr/share/locale/is',
343     '/usr/share/locale/is/LC_MESSAGES',
344     '/usr/share/locale/it',
345     '/usr/share/locale/it/LC_MESSAGES',
346     '/usr/share/locale/it_CH',
347     '/usr/share/locale/it_CH/LC_MESSAGES',
348     '/usr/share/locale/it_IT',
349     '/usr/share/locale/it_IT/LC_MESSAGES',
350     '/usr/share/locale/iu',
351     '/usr/share/locale/iu/LC_MESSAGES',
352     '/usr/share/locale/ja',
353     '/usr/share/locale/ja/LC_MESSAGES',
354     '/usr/share/locale/ja_JP.EUC',
355     '/usr/share/locale/ja_JP.EUC/LC_MESSAGES',
356     '/usr/share/locale/ja_JP.SJIS',
357     '/usr/share/locale/ja_JP.SJIS/LC_MESSAGES',
358     '/usr/share/locale/ja_JP.eucJP',
359     '/usr/share/locale/ja_JP.eucJP/LC_MESSAGES',
360     '/usr/share/locale/ka',
361     '/usr/share/locale/ka/LC_MESSAGES',
362     '/usr/share/locale/kk',
363     '/usr/share/locale/kk/LC_MESSAGES',
364     '/usr/share/locale/kl',
365     '/usr/share/locale/kl/LC_MESSAGES',
366     '/usr/share/locale/km',
367     '/usr/share/locale/km/LC_MESSAGES',
368     '/usr/share/locale/kn',
369     '/usr/share/locale/kn/LC_MESSAGES',
370     '/usr/share/locale/ko',
371     '/usr/share/locale/ko/LC_MESSAGES',
372     '/usr/share/locale/kok',
373     '/usr/share/locale/kok/LC_MESSAGES',
374     '/usr/share/locale/ku',
375     '/usr/share/locale/ku/LC_MESSAGES',
376     '/usr/share/locale/kw',
377     '/usr/share/locale/kw/LC_MESSAGES',
378     '/usr/share/locale/ky',
379     '/usr/share/locale/ky/LC_MESSAGES',
380     '/usr/share/locale/lg',
381     '/usr/share/locale/lg/LC_MESSAGES',
382     '/usr/share/locale/li',
383     '/usr/share/locale/li/LC_MESSAGES',
384     '/usr/share/locale/lo',
385     '/usr/share/locale/lo/LC_MESSAGES',
386     '/usr/share/locale/lt',
387     '/usr/share/locale/lt/LC_MESSAGES',
388     '/usr/share/locale/lv',
389     '/usr/share/locale/lv/LC_MESSAGES',
390     '/usr/share/locale/mg',
391     '/usr/share/locale/mg/LC_MESSAGES',
392     '/usr/share/locale/mi',
393     '/usr/share/locale/mi/LC_MESSAGES',
394     '/usr/share/locale/mk',
395     '/usr/share/locale/mk/LC_MESSAGES',
396     '/usr/share/locale/ml',
397     '/usr/share/locale/ml/LC_MESSAGES',
398     '/usr/share/locale/mn',
399     '/usr/share/locale/mn/LC_MESSAGES',
400     '/usr/share/locale/mr',
401     '/usr/share/locale/mr/LC_MESSAGES',
402     '/usr/share/locale/ms',
403     '/usr/share/locale/ms/LC_MESSAGES',
404     '/usr/share/locale/mt',
405     '/usr/share/locale/mt/LC_MESSAGES',
406     '/usr/share/locale/my',
407     '/usr/share/locale/my/LC_MESSAGES',
408     '/usr/share/locale/nb',
409     '/usr/share/locale/nb/LC_MESSAGES',
410     '/usr/share/locale/nb_NO',
411     '/usr/share/locale/nb_NO/LC_MESSAGES',
412     '/usr/share/locale/nds',
413     '/usr/share/locale/nds/LC_MESSAGES',
414     '/usr/share/locale/ne',
415     '/usr/share/locale/ne/LC_MESSAGES',
416     '/usr/share/locale/nl',
417     '/usr/share/locale/nl/LC_MESSAGES',
418     '/usr/share/locale/nl_BE',
419     '/usr/share/locale/nl_BE/LC_MESSAGES',
420     '/usr/share/locale/nn',
421     '/usr/share/locale/nn/LC_MESSAGES',
422     '/usr/share/locale/nn_NO',
423     '/usr/share/locale/nn_NO/LC_MESSAGES',
424     '/usr/share/locale/nso',
425     '/usr/share/locale/nso/LC_MESSAGES',
426     '/usr/share/locale/oc',
427     '/usr/share/locale/oc/LC_MESSAGES',
428     '/usr/share/locale/om',
429     '/usr/share/locale/om/LC_MESSAGES',
430     '/usr/share/locale/or',
431     '/usr/share/locale/or/LC_MESSAGES',
432     '/usr/share/locale/pa',
433     '/usr/share/locale/pa/LC_MESSAGES',
434     '/usr/share/locale/pl',
435     '/usr/share/locale/pl/LC_MESSAGES',
436     '/usr/share/locale/pl_PL',
437     '/usr/share/locale/pl_PL/LC_MESSAGES',
438     '/usr/share/locale/ps',
439     '/usr/share/locale/ps/LC_MESSAGES',
440     '/usr/share/locale/pt',
441     '/usr/share/locale/pt/LC_MESSAGES',
442     '/usr/share/locale/pt_BR',
443     '/usr/share/locale/pt_BR/LC_MESSAGES',
444     '/usr/share/locale/pt_PT',
445     '/usr/share/locale/pt_PT/LC_MESSAGES',
446     '/usr/share/locale/rm',
447     '/usr/share/locale/rm/LC_MESSAGES',
448     '/usr/share/locale/ro',
449     '/usr/share/locale/ro/LC_MESSAGES',
450     '/usr/share/locale/ru',
451     '/usr/share/locale/ru/LC_MESSAGES',
452     '/usr/share/locale/ru_RU',
453     '/usr/share/locale/ru_RU/LC_MESSAGES',
454     '/usr/share/locale/ru_UA.koi8u',
455     '/usr/share/locale/ru_UA.koi8u/LC_MESSAGES',
456     '/usr/share/locale/rw',
457     '/usr/share/locale/rw/LC_MESSAGES',
458     '/usr/share/locale/sa',
459     '/usr/share/locale/sa/LC_MESSAGES',
460     '/usr/share/locale/se',
461     '/usr/share/locale/se/LC_MESSAGES',
462     '/usr/share/locale/si',
463     '/usr/share/locale/si/LC_MESSAGES',
464     '/usr/share/locale/sid',
465     '/usr/share/locale/sid/LC_MESSAGES',
466     '/usr/share/locale/sk',
467     '/usr/share/locale/sk/LC_MESSAGES',
468     '/usr/share/locale/sl',
469     '/usr/share/locale/sl/LC_MESSAGES',
470     '/usr/share/locale/sl_SI',
471     '/usr/share/locale/sl_SI/LC_MESSAGES',
472     '/usr/share/locale/so',
473     '/usr/share/locale/so/LC_MESSAGES',
474     '/usr/share/locale/sp',
475     '/usr/share/locale/sp/LC_MESSAGES',
476     '/usr/share/locale/sq',
477     '/usr/share/locale/sq/LC_MESSAGES',
478     '/usr/share/locale/sq_AL',
479     '/usr/share/locale/sq_AL/LC_MESSAGES',
480     '/usr/share/locale/sr',
481     '/usr/share/locale/sr/LC_MESSAGES',
482     '/usr/share/locale/sr@Latn',
483     '/usr/share/locale/sr@Latn/LC_MESSAGES',
484     '/usr/share/locale/sr@ije',
485     '/usr/share/locale/sr@ije/LC_MESSAGES',
486     '/usr/share/locale/ss',
487     '/usr/share/locale/ss/LC_MESSAGES',
488     '/usr/share/locale/st',
489     '/usr/share/locale/st/LC_MESSAGES',
490     '/usr/share/locale/sv',
491     '/usr/share/locale/sv/LC_MESSAGES',
492     '/usr/share/locale/sw',
493     '/usr/share/locale/sw/LC_MESSAGES',
494     '/usr/share/locale/syr',
495     '/usr/share/locale/syr/LC_MESSAGES',
496     '/usr/share/locale/ta',
497     '/usr/share/locale/ta/LC_MESSAGES',
498     '/usr/share/locale/te',
499     '/usr/share/locale/te/LC_MESSAGES',
500     '/usr/share/locale/tg',
501     '/usr/share/locale/tg/LC_MESSAGES',
502     '/usr/share/locale/th',
503     '/usr/share/locale/th/LC_MESSAGES',
504     '/usr/share/locale/ti',
505     '/usr/share/locale/ti/LC_MESSAGES',
506     '/usr/share/locale/tig',
507     '/usr/share/locale/tig/LC_MESSAGES',
508     '/usr/share/locale/tk',
509     '/usr/share/locale/tk/LC_MESSAGES',
510     '/usr/share/locale/tl',
511     '/usr/share/locale/tl/LC_MESSAGES',
512     '/usr/share/locale/tr',
513     '/usr/share/locale/tr/LC_MESSAGES',
514     '/usr/share/locale/tt',
515     '/usr/share/locale/tt/LC_MESSAGES',
516     '/usr/share/locale/ug',
517     '/usr/share/locale/ug/LC_MESSAGES',
518     '/usr/share/locale/uk',
519     '/usr/share/locale/uk/LC_MESSAGES',
520     '/usr/share/locale/uk_UA',
521     '/usr/share/locale/uk_UA/LC_MESSAGES',
522     '/usr/share/locale/ur',
523     '/usr/share/locale/ur/LC_MESSAGES',
524     '/usr/share/locale/urd',
525     '/usr/share/locale/urd/LC_MESSAGES',
526     '/usr/share/locale/uz',
527     '/usr/share/locale/uz/LC_MESSAGES',
528     '/usr/share/locale/uz@cyrillic',
529     '/usr/share/locale/uz@cyrillic/LC_MESSAGES',
530     '/usr/share/locale/ve',
531     '/usr/share/locale/ve/LC_MESSAGES',
532     '/usr/share/locale/ven',
533     '/usr/share/locale/ven/LC_MESSAGES',
534     '/usr/share/locale/vi',
535     '/usr/share/locale/vi/LC_MESSAGES',
536     '/usr/share/locale/wa',
537     '/usr/share/locale/wa/LC_MESSAGES',
538     '/usr/share/locale/wal',
539     '/usr/share/locale/wal/LC_MESSAGES',
540     '/usr/share/locale/wo',
541     '/usr/share/locale/wo/LC_MESSAGES',
542     '/usr/share/locale/xh',
543     '/usr/share/locale/xh/LC_MESSAGES',
544     '/usr/share/locale/yi',
545     '/usr/share/locale/yi/LC_MESSAGES',
546     '/usr/share/locale/yo',
547     '/usr/share/locale/yo/LC_MESSAGES',
548     '/usr/share/locale/zh',
549     '/usr/share/locale/zh/LC_MESSAGES',
550     '/usr/share/locale/zh_CN',
551     '/usr/share/locale/zh_CN.GB2312',
552     '/usr/share/locale/zh_CN.GB2312/LC_MESSAGES',
553     '/usr/share/locale/zh_CN/LC_MESSAGES',
554     '/usr/share/locale/zh_HK',
555     '/usr/share/locale/zh_HK/LC_MESSAGES',
556     '/usr/share/locale/zh_TW',
557     '/usr/share/locale/zh_TW.Big5',
558     '/usr/share/locale/zh_TW.Big5/LC_MESSAGES',
559     '/usr/share/locale/zh_TW/LC_MESSAGES',
560     '/usr/share/locale/zu',
561     '/usr/share/locale/zu/LC_MESSAGES',
562     '/usr/share/man',
563     '/usr/share/man/man1',
564     '/usr/share/man/man2',
565     '/usr/share/man/man3',
566     '/usr/share/man/man4',
567     '/usr/share/man/man5',
568     '/usr/share/man/man6',
569     '/usr/share/man/man7',
570     '/usr/share/man/man8',
571     '/usr/share/man/man9',
572     '/usr/share/man/mann',
573     '/usr/share/mime',
574     '/usr/share/mime/packages',
575     '/usr/share/misc',
576     '/usr/share/nls',
577     '/usr/share/pixmaps',
578     '/usr/share/pkgconfig',
579     '/usr/share/sgml',
580     '/usr/share/sgml/docbook',
581     '/usr/share/sounds',
582     '/usr/share/themes',
583     '/usr/share/tmac',
584     '/usr/share/xml',
585     '/usr/share/xml/docbook',
586     '/usr/share/xsessions',
587     '/usr/src',
588     '/usr/src/packages',
589     '/usr/tmp',
590     '/var',
591     '/var/X11R6',
592     '/var/adm',
593     '/var/adm/backup',
594     '/var/adm/backup/rpmdb',
595     '/var/adm/backup/sysconfig',
596     '/var/adm/fillup-templates',
597     '/var/adm/perl-modules',
598     '/var/cache',
599     '/var/cache/fonts',
600     '/var/cache/man',
601     '/var/games',
602     '/var/lib',
603     '/var/lib/empty',
604     '/var/lib/misc',
605     '/var/lib/news',
606     '/var/lib/nobody',
607     '/var/lib/pam_devperm',
608     '/var/lib/wwwrun',
609     '/var/lock',
610     '/var/lock/subsys',
611     '/var/log',
612     '/var/mail',
613     '/var/opt',
614     '/var/run',
615     '/var/spool',
616     '/var/spool/clientmqueue',
617     '/var/spool/locks',
618     '/var/spool/lpd',
619     '/var/spool/mail',
620     '/var/spool/uucp',
621     '/var/spool/uucp/uucp',
622     '/var/tmp',
623     '/var/tmp/vi.recover',
624     )
625
626 DEFAULT_GAMES_GROUPS = 'Games'
627
628 DEFAULT_DANGLING_EXCEPTIONS = (['consolehelper$', 'usermode-consoleonly'],
629                                )
630
631 # Standard users and groups from LSB Core 4.0.0: 21.2 User & Group Names
632 DEFAULT_STANDARD_USERS  = ('root', 'bin', 'daemon', 'adm', 'lp', 'sync',
633                            'shutdown', 'halt', 'mail', 'news', 'uucp',
634                            'operator', 'man', 'nobody',)
635 DEFAULT_STANDARD_GROUPS = ('root', 'bin', 'daemon', 'adm', 'lp', 'sync',
636                            'shutdown', 'halt', 'mail', 'news', 'uucp',
637                            'man', 'nobody',)
638
639 tmp_regex = re.compile('^/tmp/|^(/var|/usr)/tmp/')
640 sub_bin_regex = re.compile('^(/usr)?/s?bin/\S+/')
641 backup_regex = re.compile('(~|\#[^/]+\#|\.orig|\.rej)$')
642 compr_regex = re.compile('\.(gz|z|Z|zip|bz2|lzma|xz)$')
643 absolute_regex = re.compile('^/([^/]+)')
644 absolute2_regex = re.compile('^/?([^/]+)')
645 points_regex = re.compile('^\.\./(.*)')
646 doc_regex = re.compile('^/usr(/share|/X11R6)?/(doc|man|info)/|^/opt/kde3/share/doc|^/usr/share/gnome/help')
647 bin_regex = re.compile('^/(?:usr/(?:s?bin|games)|s?bin)/(.*)')
648 includefile_regex = re.compile('\.(c|h)(pp|xx)?$', re.IGNORECASE)
649 develfile_regex = re.compile('\.(a|cmxa?|mli?|gir)$')
650 buildconfigfile_regex = re.compile('(\.pc|/bin/.+-config)$')
651 docdir_examples_regex = re.compile('^/usr/(?:share/doc/packages|lib(?:64))/[^/]+/(?:example|demo|script|contrib)')
652 # room for improvement with catching more -R, but also for false positives...
653 buildconfig_rpath_regex = re.compile('(?:-rpath|Wl,-R)\\b')
654 sofile_regex = re.compile('/lib(64)?/(.+/)?lib[^/]+\.so$')
655 devel_regex = re.compile('(.*)-(debug(info)?|devel|headers|source|static)$')
656 debuginfo_package_regex = re.compile('-debug(info)?$')
657 lib_regex = re.compile('/lib(64)?/lib[^/]*\.so\.[\d\.-]*$')
658 ldconfig_regex = re.compile('^[^#]*ldconfig', re.MULTILINE)
659 depmod_regex = re.compile('^[^#]*depmod', re.MULTILINE)
660 install_info_regex = re.compile('^[^#]*install-info', re.MULTILINE)
661 perl_temp_file_regex = re.compile('.*perl.*/(\.packlist|perllocal\.pod)$')
662 scm_regex=re.compile('/(CVS|RCS)(/[^/]+)?$|/\.(bzr|cvs|git|hg)ignore$|/\.hgtags$|/\.(bzr|git|hg|svn)/|/(\.arch-ids|{arch})/|,v$')
663 games_path_regex = re.compile('^/usr(/lib(64)?)?/games/')
664 games_group_regex = re.compile(Config.getOption('RpmGamesGroups', DEFAULT_GAMES_GROUPS))
665 dangling_exceptions = Config.getOption('DanglingSymlinkExceptions', DEFAULT_DANGLING_EXCEPTIONS)
666 logrotate_regex = re.compile('^/etc/logrotate\.d/(.*)')
667 module_rpms_ok = Config.getOption('KernelModuleRPMsOK', True)
668 kernel_modules_regex = re.compile('^/lib/modules/(2\.[23456]\.[0-9]+[^/]*?)/')
669 kernel_package_regex = re.compile('^kernel(22)?(-)?(smp|enterprise|bigmem|secure|BOOT|i686-up-4GB|p3-smp-64GB)?')
670 normal_zero_length_regex = re.compile('^/etc/security/console\.apps/|/\.nosearch$|/__init__\.py$')
671 perl_regex = re.compile('^/usr/lib/perl5/(?:vendor_perl/)?([0-9]+\.[0-9]+)\.([0-9]+)/')
672 python_regex = re.compile('^/usr/lib(?:64)?/python([.0-9]+)/')
673 python_bytecode_regex_pep3147 = re.compile('^(.*)/__pycache__/(.*)\.(.*)(\.py[oc])$')
674 python_bytecode_regex = re.compile('^(.*)(\.py[oc])$')
675 python_default_version = Config.getOption('PythonDefaultVersion', None)
676 perl_version_trick = Config.getOption('PerlVersionTrick', True)
677 log_regex = re.compile('^/var/log/[^/]+$')
678 lib_path_regex = re.compile('^(/usr(/X11R6)?)?/lib(64)?')
679 lib_package_regex = re.compile('^(lib|.+-libs)')
680 hidden_file_regex = re.compile('/\.[^/]*$')
681 manifest_perl_regex = re.compile('^/usr/share/doc/perl-.*/MANIFEST(\.SKIP)?$')
682 shebang_regex = re.compile('^#!\s*(\S+)')
683 interpreter_regex = re.compile('^/(usr/)?(s?bin|games|libexec(/.+)?|(lib(64)?|share)/.+)/[^/]+$')
684 script_regex = re.compile('^/((usr/)?s?bin|etc/(rc\.d/init\.d|X11/xinit\.d|cron\.(hourly|daily|monthly|weekly)))/')
685 sourced_script_regex = re.compile('^/etc/(bash_completion\.d|profile\.d|/sbin/conf.d)/')
686 use_utf8 = Config.getOption('UseUTF8', Config.USEUTF8_DEFAULT)
687 skipdocs_regex = re.compile(Config.getOption('SkipDocsRegexp', '\.(?:rtf|x?html?|svg|ml[ily]?)$'), re.IGNORECASE)
688 meta_package_regex = re.compile(Config.getOption('MetaPackageRegexp', '^(bundle|task)-'))
689 filesys_packages = ['filesystem'] # TODO: make configurable?
690 quotes_regex = re.compile('[\'"]+')
691
692 for idx in range(0, len(dangling_exceptions)):
693     dangling_exceptions[idx][0] = re.compile(dangling_exceptions[idx][0])
694 del idx
695
696 use_relative_symlinks = Config.getOption("UseRelativeSymlinks", True)
697
698 standard_groups = Config.getOption('StandardGroups', DEFAULT_STANDARD_GROUPS)
699 standard_users = Config.getOption('StandardUsers', DEFAULT_STANDARD_USERS)
700
701 non_readable_regexs = (re.compile('^/var/log/'),
702                        re.compile('^/etc/(g?shadow-?|securetty)$'))
703
704 man_base_regex = re.compile(r'^/usr(?:/share)?/man/man[^/]+/(.+)\.[1-9n]')
705 man_warn_regex = re.compile(r'^([^:]+:)\d+:\s*')
706 man_nowarn_regex = re.compile(
707     # From Lintian: ignore common undefined macros from pod2man << Perl 5.10
708     r'\`(Tr|IX)\' not defined|'
709     # .so entries won't resolve as we're dealing with stdin
710     r'No such file or directory|'
711     # TODO, better handling for these (see e.g. Lintian)
712     r'(can\'t break|cannot adjust) line')
713 man_warn_category = Config.getOption('ManWarningCategory', 'mac')
714
715 fsf_license_regex = re.compile('(GNU((\s+(Library|Lesser|Affero))?(\s+General)?\s+Public|\s+Free\s+Documentation)\s+Licen[cs]e|(GP|FD)L)', re.IGNORECASE)
716 fsf_wrong_address_regex = re.compile('(675\s+Mass\s+Ave|59\s+Temple\s+Place|Franklin\s+Steet|02139|02111-1307)', re.IGNORECASE)
717
718 # loosely inspired from Python Cookbook
719 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/173220
720 text_characters = "".join(map(chr, range(32, 127)) + list("\n\r\t\b"))
721 _null_trans = string.maketrans("", "")
722
723 def peek(filename, pkg, length=1024):
724     """Peek into a file, return a chunk from its beginning and a flag if it
725        seems to be a text file."""
726     fobj = None
727     chunk = None
728     try:
729         fobj = open(filename, 'rb')
730         chunk = fobj.read(length)
731         fobj.close()
732     except Exception, e: # eg. https://bugzilla.redhat.com/209876
733         printWarning(pkg, 'read-error', e)
734         if fobj:
735             fobj.close()
736         return (chunk, False)
737
738     if "\0" in chunk:
739         return (chunk, False)
740
741     if not chunk:  # Empty files are considered text
742         return (chunk, True)
743
744     # PDF's are binary but often detected as text by the algorithm below
745     if filename.lower().endswith('.pdf') and chunk.startswith('%PDF-'):
746         return (chunk, False)
747
748     # Get the non-text characters (maps a character to itself then
749     # use the 'remove' option to get rid of the text characters.)
750     t = chunk.translate(_null_trans, text_characters)
751
752     # If more than 30% non-text characters, then consider it a binary file
753     istext = float(len(t))/len(chunk) <= 0.30
754     return (chunk, istext)
755
756 # See Python/import.c (in the default and 2.x branches) for a full list of
757 # the values here.
758 _python_magic_values = {
759     '2.2': 60717,
760     '2.3': 62011,
761     '2.4': 62061,
762     '2.5': 62131,
763     '2.6': 62161,
764     '2.7': 62211,
765     '3.0': 3130,
766     '3.1': 3150,
767     '3.2': 3180,
768     '3.3': 3230,
769     }
770
771 def get_expected_pyc_magic(path):
772     """.pyc/.pyo files embed a 4-byte magic value identifying which version of
773     the python bytecode ABI they are for. Given a path to a .pyc/.pyo file,
774     return a (magic ABI value, python version) tuple.  For example,
775     '/usr/lib/python3.1/foo.pyc' should return (3151, '3.1').
776     The first value will be None if the python version was not resolved
777     from the given pathname and the PythonDefaultVersion configuration
778     variable is not set, or if we don't know the magic ABI value for the
779     python version (no matter from which source the version came from).
780     The second value will be None if a python version could not be resolved
781     from the given pathname."""
782
783     ver_from_path = None
784     m = python_regex.search(path)
785     if m:
786         ver_from_path = m.group(1)
787
788     expected_version = ver_from_path or python_default_version
789     expected_magic_value = _python_magic_values.get(expected_version)
790
791     if not expected_magic_value:
792         return (None, ver_from_path)
793
794     # In Python 2, if Py_UnicodeFlag is set, Python's import code uses a value
795     # one higher, but this is off by default. In Python 3.0 and 3.1 (but no
796     # longer in 3.2), it always uses the value one higher:
797     if expected_version[:3] in ('3.0', '3.1'):
798         expected_magic_value += 1
799
800     return (expected_magic_value, ver_from_path)
801
802 def py_demarshal_long(b):
803     """Counterpart to Python's PyMarshal_ReadLongFromFile, operating on the
804     bytes in a string."""
805     return (ord(b[0])
806             + (ord(b[1]) << 8)
807             + (ord(b[2]) << 16)
808             + (ord(b[3]) << 24))
809
810 def python_bytecode_to_script(path):
811     """Given a python bytecode path, give the path of the .py file
812     (or None if not python bytecode)."""
813
814     res = python_bytecode_regex_pep3147.search(path)
815     if res:
816         return res.group(1) + '/' + res.group(2) + '.py'
817
818     res = python_bytecode_regex.search(path)
819     if res:
820         return res.group(1) + '.py'
821
822     return None
823
824 class FilesCheck(AbstractCheck.AbstractCheck):
825
826     def __init__(self):
827         AbstractCheck.AbstractCheck.__init__(self, 'FilesCheck')
828
829     def check(self, pkg):
830
831         files = pkg.files()
832
833         if use_utf8:
834             for filename in files:
835                 if not is_utf8_str(filename):
836                     printError(pkg, 'filename-not-utf8', filename)
837
838         # Rest of the checks are for binary packages only
839         if pkg.isSource():
840             return
841
842         # Check if the package is a development package
843         devel_pkg = devel_regex.search(pkg.name)
844
845         for p in pkg.provides():
846             if not devel_pkg and devel_regex.search(p[0]):
847                 devel_pkg = True
848
849         config_files = pkg.configFiles()
850         ghost_files = pkg.ghostFiles()
851         doc_files = pkg.docFiles()
852         req_names = pkg.req_names()
853         lib_package = lib_package_regex.search(pkg.name)
854         is_kernel_package = kernel_package_regex.search(pkg.name)
855         debuginfo_package = debuginfo_package_regex.search(pkg.name)
856
857         # report these errors only once
858         perl_dep_error = False
859         python_dep_error = False
860         lib_file = False
861         non_lib_file = None
862         log_file = None
863         logrotate_file = False
864         debuginfo_srcs = False
865         debuginfo_debugs = False
866
867         if not lib_package and not doc_files:
868             printWarning(pkg, 'no-documentation')
869
870         if files:
871             if meta_package_regex.search(pkg.name):
872                 printWarning(pkg, 'file-in-meta-package')
873         elif debuginfo_package:
874             printError(pkg, 'empty-debuginfo-package')
875
876         # Unique (rdev, inode) combinations
877         hardlinks = {}
878
879         # All executable files from standard bin dirs (basename => [paths])
880         # Hack: basenames with empty paths links are symlinks (not subject
881         # to duplicate binary check, but yes for man page existence check)
882         bindir_exes = {}
883
884         # All man page "base" names (without section etc extensions)
885         man_basenames = set()
886
887         for f, pkgfile in files.items():
888             mode = pkgfile.mode
889             user = pkgfile.user
890             group = pkgfile.group
891             link = pkgfile.linkto
892             size = pkgfile.size
893             rdev = pkgfile.rdev
894             inode = pkgfile.inode
895             is_doc = f in doc_files
896             nonexec_file = False
897
898             for match in AbstractCheck.macro_regex.findall(f):
899                 printWarning(pkg, 'unexpanded-macro', f, match)
900             if standard_users and user not in standard_users:
901                 printWarning(pkg, 'non-standard-uid', f, user)
902             if standard_groups and group not in standard_groups:
903                 printWarning(pkg, 'non-standard-gid', f, group)
904
905             if not module_rpms_ok and kernel_modules_regex.search(f) and not \
906                     is_kernel_package:
907                 printError(pkg, "kernel-modules-not-in-kernel-packages", f)
908
909             if tmp_regex.search(f):
910                 printError(pkg, 'dir-or-file-in-tmp', f)
911             elif f.startswith('/mnt/'):
912                 printError(pkg, 'dir-or-file-in-mnt', f)
913             elif f.startswith('/opt/'):
914                 printError(pkg, 'dir-or-file-in-opt', f)
915             elif f.startswith('/usr/local/'):
916                 printError(pkg, 'dir-or-file-in-usr-local', f)
917             elif f.startswith('/var/local/'):
918                 printError(pkg, 'dir-or-file-in-var-local', f)
919             elif f.startswith('/var/run/'):
920                 if f not in ghost_files:
921                     printWarning(pkg, 'non-ghost-in-var-run', f)
922             elif f.startswith('/var/lock/'):
923                 if f not in ghost_files:
924                     printWarning(pkg, 'non-ghost-in-var-lock', f)
925             elif sub_bin_regex.search(f):
926                 printError(pkg, 'subdir-in-bin', f)
927             elif f.startswith('/home/'):
928                 printError(pkg, 'dir-or-file-in-home', f)
929             elif '/site_perl/' in f:
930                 printWarning(pkg, 'siteperl-in-perl-module', f)
931
932             if backup_regex.search(f):
933                 printError(pkg, 'backup-file-in-package', f)
934             elif scm_regex.search(f):
935                 printError(pkg, 'version-control-internal-file', f)
936             elif f.endswith('/.htaccess'):
937                 printError(pkg, 'htaccess-file', f)
938             elif hidden_file_regex.search(f) and not f.startswith("/etc/skel/"):
939                 printWarning(pkg, 'hidden-file-or-dir', f)
940             elif manifest_perl_regex.search(f):
941                 printWarning(pkg, 'manifest-in-perl-module', f)
942             elif f == '/usr/info/dir' or f == '/usr/share/info/dir':
943                 printError(pkg, 'info-dir-file', f)
944
945             res = logrotate_regex.search(f)
946             if res:
947                 logrotate_file = True
948                 if res.group(1) != pkg.name:
949                     printError(pkg, 'incoherent-logrotate-file', f)
950
951             deps=[x[0] for x in pkg.requires()+pkg.recommends()+pkg.suggests()]
952             if res and not ('logrotate' in deps) and pkg.name != "logrotate":
953                 printError(pkg, 'missing-dependency-to-logrotate', "for logrotate script", f)
954             if f.startswith('/etc/cron.') \
955                and not ('cron' in deps) and pkg.name != "cron":
956                 printError(pkg, 'missing-dependency-to-cron', "for cron script", f)
957             if f.startswith('/etc/xinet.d/') \
958                and not ('xinetd' in deps) and pkg.name != "xinetd":
959                 printError(pkg, 'missing-dependency-to-xinetd', "for xinet.d script", f)
960
961             if link != '':
962                 ext = compr_regex.search(link)
963                 if ext:
964                     if not re.compile('\.' + ext.group(1) + '$').search(f):
965                         printError(pkg, 'compressed-symlink-with-wrong-ext',
966                                    f, link)
967
968             perm = mode & 07777
969
970             if log_regex.search(f):
971                 log_file = f
972
973             # Hardlink check
974             hardlink = hardlinks.get((rdev, inode))
975             if hardlink and os.path.dirname(hardlink) != os.path.dirname(f):
976                 printWarning(pkg, 'cross-directory-hard-link', f, hardlink)
977             hardlinks[(rdev, inode)] = f
978
979             # normal file check
980             if stat.S_ISREG(mode):
981
982                 # set[ug]id bit check
983                 if stat.S_ISGID & mode or stat.S_ISUID & mode:
984                     if stat.S_ISUID & mode:
985                         printError(pkg, 'setuid-binary', f, user, oct(perm))
986                     if stat.S_ISGID & mode:
987                         if not (group == 'games' and
988                                 (games_path_regex.search(f) or
989                                  games_group_regex.search(
990                                     pkg[rpm.RPMTAG_GROUP]))):
991                             printError(pkg, 'setgid-binary', f, group,
992                                        oct(perm))
993                     if mode & 0777 != 0755:
994                         printError(pkg, 'non-standard-executable-perm', f,
995                                    oct(perm))
996
997                 # Prefetch scriptlets, strip quotes from them (#169)
998                 postin = pkg[rpm.RPMTAG_POSTIN] or \
999                     pkg.scriptprog(rpm.RPMTAG_POSTINPROG)
1000                 if postin:
1001                     postin = quotes_regex.sub('', postin)
1002                 postun = pkg[rpm.RPMTAG_POSTUN] or \
1003                     pkg.scriptprog(rpm.RPMTAG_POSTUNPROG)
1004                 if postun:
1005                     postun = quotes_regex.sub('', postun)
1006
1007                 if not devel_pkg:
1008                     if lib_path_regex.search(f):
1009                         lib_file = True
1010                     elif not is_doc:
1011                         non_lib_file = f
1012
1013                 if log_regex.search(f):
1014                     nonexec_file = True
1015                     if user != 'root':
1016                         printError(pkg, 'non-root-user-log-file', f, user)
1017                     if group != 'root':
1018                         printError(pkg, 'non-root-group-log-file', f, group)
1019                     if f not in ghost_files:
1020                         printError(pkg, 'non-ghost-file', f)
1021
1022                 chunk = None
1023                 istext = False
1024                 if os.access(pkgfile.path, os.R_OK):
1025                     (chunk, istext) = peek(pkgfile.path, pkg)
1026
1027                 interpreter = None
1028                 if chunk:
1029                     res = shebang_regex.search(chunk)
1030                     if res:
1031                         interpreter = res.group(1)
1032
1033                 if doc_regex.search(f):
1034                     if not interpreter:
1035                         nonexec_file = True
1036                     if not is_doc:
1037                         printError(pkg, 'not-listed-as-documentation', f)
1038
1039                 # check ldconfig call in %post and %postun
1040                 if lib_regex.search(f):
1041                     if not postin:
1042                         printError(pkg, 'library-without-ldconfig-postin', f)
1043                     else:
1044                         if not ldconfig_regex.search(postin):
1045                             printError(pkg, 'postin-without-ldconfig', f)
1046
1047                     if not postun:
1048                         printError(pkg, 'library-without-ldconfig-postun', f)
1049                     else:
1050                         if not ldconfig_regex.search(postun):
1051                             printError(pkg, 'postun-without-ldconfig', f)
1052
1053                 # check depmod call in %post and %postun
1054                 res = not is_kernel_package and kernel_modules_regex.search(f)
1055                 if res:
1056                     kernel_version = res.group(1)
1057                     kernel_version_regex = re.compile(
1058                         '\\bdepmod\s+-a.*F\s+/boot/System\.map-' +
1059                         re.escape(kernel_version) + '\\b.*\\b' +
1060                         re.escape(kernel_version) + '\\b',
1061                         re.MULTILINE | re.DOTALL)
1062
1063                     if not postin or not depmod_regex.search(postin):
1064                         printError(pkg, 'module-without-depmod-postin', f)
1065                     # check that we run depmod on the right kernel
1066                     elif not kernel_version_regex.search(postin):
1067                         printError(pkg, 'postin-with-wrong-depmod', f)
1068
1069                     if not postun or not depmod_regex.search(postun):
1070                         printError(pkg, 'module-without-depmod-postun', f)
1071                     # check that we run depmod on the right kernel
1072                     elif not kernel_version_regex.search(postun):
1073                         printError(pkg, 'postun-with-wrong-depmod', f)
1074
1075                 # check install-info call in %post and %postun
1076                 if f.startswith('/usr/share/info/'):
1077                     if not postin:
1078                         printError(pkg,
1079                                    'info-files-without-install-info-postin', f)
1080                     elif not install_info_regex.search(postin):
1081                         printError(pkg, 'postin-without-install-info', f)
1082
1083                     preun = pkg[rpm.RPMTAG_PREUN] or \
1084                         pkg.scriptprog(rpm.RPMTAG_PREUNPROG)
1085                     if not postun and not preun:
1086                         printError(pkg,
1087                                    'info-files-without-install-info-postun', f)
1088                     elif (not postun or
1089                           not install_info_regex.search(postun)) and \
1090                           (not preun or not install_info_regex.search(preun)):
1091                         printError(pkg, 'postin-without-install-info', f)
1092
1093                 # check perl temp file
1094                 if perl_temp_file_regex.search(f):
1095                     printWarning(pkg, 'perl-temp-file', f)
1096
1097                 is_buildconfig = buildconfigfile_regex.search(f) and True
1098
1099                 # check rpaths in buildconfig files
1100                 if is_buildconfig:
1101                     ln = pkg.grep(buildconfig_rpath_regex, f)
1102                     if ln:
1103                         printError(pkg, 'rpath-in-buildconfig', f, 'lines', ln)
1104
1105                 res = bin_regex.search(f)
1106                 if res:
1107                     if mode & 0111 == 0:
1108                         printWarning(pkg, 'non-executable-in-bin', f, oct(perm))
1109                     else:
1110                         exe = res.group(1)
1111                         if "/" not in exe:
1112                             bindir_exes.setdefault(exe, []).append(f)
1113
1114                 if not devel_pkg and not is_doc and \
1115                        (includefile_regex.search(f) or \
1116                         develfile_regex.search(f) or is_buildconfig):
1117                     printWarning(pkg, 'devel-file-in-non-devel-package', f)
1118                 if mode & 0444 != 0444 and perm & 07000 == 0:
1119                     ok_nonreadable = False
1120                     for regex in non_readable_regexs:
1121                         if regex.search(f):
1122                             ok_nonreadable = True
1123                             break
1124                     if not ok_nonreadable:
1125                         printError(pkg, 'non-readable', f, oct(perm))
1126                 if size == 0 and not normal_zero_length_regex.search(f) and \
1127                         f not in ghost_files:
1128                     printError(pkg, 'zero-length', f)
1129
1130                 if mode & 0002 != 0:
1131                     printError(pkg, 'world-writable', f, oct(perm))
1132
1133                 if not perl_dep_error:
1134                     res = perl_regex.search(f)
1135                     if res:
1136                         if perl_version_trick:
1137                             vers = res.group(1) + '.' + res.group(2)
1138                         else:
1139                             vers = res.group(1) + res.group(2)
1140                         if not (pkg.check_versioned_dep('perl-base', vers) or
1141                                 pkg.check_versioned_dep('perl', vers)):
1142                             printError(pkg, 'no-dependency-on',
1143                                        'perl-base', vers)
1144                             perl_dep_error = True
1145
1146                 if not python_dep_error:
1147                     res = python_regex.search(f)
1148                     if res and not (pkg.check_versioned_dep('python-base',
1149                                                             res.group(1)) or
1150                                     pkg.check_versioned_dep('python',
1151                                                             res.group(1)) or
1152                                     pkg.check_versioned_dep('python(abi)',
1153                                                             res.group(1))
1154                                     ):
1155                         printError(pkg, 'no-dependency-on', 'python(abi)',
1156                                    res.group(1))
1157                         python_dep_error = True
1158
1159                 source_file = python_bytecode_to_script(f)
1160                 if source_file:
1161                     if source_file in files:
1162                         if chunk:
1163                             # Verify that the magic ABI value embedded in the
1164                             # .pyc header is correct
1165                             found_magic = py_demarshal_long(chunk[:4]) & 0xffff
1166                             exp_magic, exp_version = get_expected_pyc_magic(f)
1167                             if exp_magic and found_magic != exp_magic:
1168                                 found_version = 'unknown'
1169                                 for (pv, pm) in _python_magic_values.items():
1170                                     if pm == found_magic:
1171                                         found_version = pv
1172                                         break
1173                                 # If expected version was from the file path,
1174                                 # issue # an error, otherwise a warning.
1175                                 msg = (pkg, 'python-bytecode-wrong-magic-value',
1176                                        f, "expected %d (%s), found %d (%s)" %
1177                                        (exp_magic,
1178                                         exp_version or python_default_version,
1179                                         found_magic, found_version))
1180                                 if exp_version is not None:
1181                                     printError(*msg)
1182                                 else:
1183                                     printWarning(*msg)
1184
1185                             # Verify that the timestamp embedded in the .pyc
1186                             # header matches the mtime of the .py file:
1187                             pyc_timestamp = py_demarshal_long(chunk[4:8])
1188                             # If it's a symlink, check target file mtime.
1189                             srcfile = pkg.readlink(files[source_file])
1190                             if not srcfile:
1191                                 printWarning(
1192                                     pkg, 'python-bytecode-without-source', f)
1193                             elif pyc_timestamp != srcfile.mtime:
1194                                 cts = datetime.fromtimestamp(
1195                                     pyc_timestamp).isoformat()
1196                                 sts = datetime.fromtimestamp(
1197                                     srcfile.mtime).isoformat()
1198                                 printError(pkg,
1199                                            'python-bytecode-inconsistent-mtime',
1200                                            f, cts, srcfile.name, sts)
1201                     else:
1202                         printWarning(pkg, 'python-bytecode-without-source', f)
1203
1204                 # normal executable check
1205                 if mode & stat.S_IXUSR and perm != 0755:
1206                     printError(pkg, 'non-standard-executable-perm',
1207                                f, oct(perm))
1208                 if mode & 0111 != 0:
1209                     if f in config_files:
1210                         printError(pkg, 'executable-marked-as-config-file', f)
1211                     if not nonexec_file:
1212                         # doc_regex and log_regex checked earlier, no match,
1213                         # check rest of usual cases here.  Sourced scripts have
1214                         # their own check, so disregard them here.
1215                         nonexec_file = f.endswith('.pc') or \
1216                                        compr_regex.search(f) or \
1217                                        includefile_regex.search(f) or \
1218                                        develfile_regex.search(f) or \
1219                                        logrotate_regex.search(f)
1220                     if nonexec_file and not docdir_examples_regex.search(f):
1221                         printWarning(pkg, 'spurious-executable-perm', f)
1222                 elif f.startswith('/etc/') and f not in config_files and \
1223                         f not in ghost_files and not f.endswith(".desktop"):
1224                     printWarning(pkg, 'non-conffile-in-etc', f)
1225
1226                 if pkg.arch == 'noarch' and f.startswith('/usr/lib64/python'):
1227                     printError(pkg, 'noarch-python-in-64bit-path', f)
1228
1229                 if debuginfo_package:
1230                     if f.endswith('.debug'):
1231                         debuginfo_debugs = True
1232                     else:
1233                         debuginfo_srcs = True
1234
1235                 res = man_base_regex.search(f)
1236                 if res:
1237                     man_basenames.add(res.group(1))
1238                     if use_utf8 and chunk:
1239                         # TODO: better shell escaping or seq based invocation
1240                         cmd = commands.getstatusoutput(
1241                             'env LC_ALL=C %s "%s" | gtbl | '
1242                             'env LC_ALL=en_US.UTF-8 groff -mtty-char -Tutf8 '
1243                             '-P-c -mandoc -w%s >/dev/null' %
1244                             (catcmd(f), pkgfile.path, man_warn_category))
1245                         for line in cmd[1].split("\n"):
1246                             res = man_warn_regex.search(line)
1247                             if not res or man_nowarn_regex.search(line):
1248                                 continue
1249                             printWarning(pkg, "manual-page-warning", f,
1250                                          line[res.end(1):])
1251
1252                 # text file checks
1253                 if istext:
1254                     # ignore perl module shebang -- TODO: disputed...
1255                     if f.endswith('.pm'):
1256                         interpreter = None
1257                     # sourced scripts should not be executable
1258                     if sourced_script_regex.search(f):
1259                         if interpreter:
1260                             printError(pkg,
1261                                        'sourced-script-with-shebang', f,
1262                                        interpreter)
1263                         if mode & 0111 != 0:
1264                             printError(pkg, 'executable-sourced-script',
1265                                        f, oct(perm))
1266                     # ...but executed ones should
1267                     elif interpreter or mode & 0111 != 0 or \
1268                             script_regex.search(f):
1269                         if interpreter:
1270                             if mode & 0111 != 0 and not interpreter_regex.search(interpreter):
1271                                 printError(pkg, 'wrong-script-interpreter',
1272                                            f, interpreter)
1273                         elif not nonexec_file and not \
1274                                 (lib_path_regex.search(f) and
1275                                  f.endswith('.la')):
1276                             printError(pkg, 'script-without-shebang', f)
1277
1278                         if mode & 0111 == 0 and not is_doc and \
1279                            interpreter and interpreter.startswith("/"):
1280                             printError(pkg, 'non-executable-script', f,
1281                                        oct(perm), interpreter)
1282                         if '\r' in chunk:
1283                             printError(
1284                                 pkg, 'wrong-script-end-of-line-encoding', f)
1285                     elif is_doc and not skipdocs_regex.search(f):
1286                         if '\r' in chunk:
1287                             printWarning(
1288                                 pkg, 'wrong-file-end-of-line-encoding', f)
1289                         # We check only doc text files for UTF-8-ness;
1290                         # checking everything may be slow and can generate
1291                         # lots of unwanted noise.
1292                         if use_utf8 and not is_utf8(pkgfile.path):
1293                             printWarning(pkg, 'file-not-utf8', f)
1294                     if fsf_license_regex.search(chunk) and \
1295                             fsf_wrong_address_regex.search(chunk):
1296                         printError(pkg, 'incorrect-fsf-address', f)
1297
1298                 elif is_doc and chunk and compr_regex.search(f):
1299                     ff = compr_regex.sub('', f)
1300                     if not skipdocs_regex.search(ff):
1301                         # compressed docs, eg. info and man files etc
1302                         if use_utf8 and not is_utf8(pkgfile.path):
1303                             printWarning(pkg, 'file-not-utf8', f)
1304
1305             # normal dir check
1306             elif stat.S_ISDIR(mode):
1307                 if mode & 01002 == 2: # world writable without sticky bit
1308                     printError(pkg, 'world-writable', f, oct(perm))
1309                 if perm != 0755:
1310                     printError(pkg, 'non-standard-dir-perm', f, oct(perm))
1311                 if pkg.name not in filesys_packages and f in STANDARD_DIRS:
1312                     printError(pkg, 'standard-dir-owned-by-package', f)
1313                 if hidden_file_regex.search(f):
1314                     printWarning(pkg, 'hidden-file-or-dir', f)
1315
1316
1317             # symbolic link check
1318             elif stat.S_ISLNK(mode):
1319
1320                 is_so = sofile_regex.search(f)
1321                 if not devel_pkg and is_so and not link.endswith('.so'):
1322                     printWarning(pkg, 'devel-file-in-non-devel-package', f)
1323
1324                 res = man_base_regex.search(f)
1325                 if res:
1326                     man_basenames.add(res.group(1))
1327                 else:
1328                     res = bin_regex.search(f)
1329                     if res:
1330                         exe = res.group(1)
1331                         if "/" not in exe:
1332                             bindir_exes.setdefault(exe, [])
1333
1334                 # absolute link
1335                 r = absolute_regex.search(link)
1336                 if r:
1337                     if not is_so and link not in files and \
1338                             link not in req_names:
1339                         is_exception = False
1340                         for e in dangling_exceptions:
1341                             if e[0].search(link):
1342                                 is_exception = e[1]
1343                                 break
1344                         if is_exception:
1345                             if is_exception not in req_names:
1346                                 printWarning(pkg, 'no-dependency-on',
1347                                              is_exception)
1348                         else:
1349                             printWarning(pkg, 'dangling-symlink', f, link)
1350                     linktop = r.group(1)
1351                     r = absolute_regex.search(f)
1352                     if r:
1353                         filetop = r.group(1)
1354                         if filetop == linktop or use_relative_symlinks:
1355                             printWarning(pkg, 'symlink-should-be-relative',
1356                                          f, link)
1357                 # relative link
1358                 else:
1359                     if not is_so:
1360                         abslink = '%s/%s' % (os.path.dirname(f), link)
1361                         abslink = os.path.normpath(abslink)
1362                         if abslink not in files and abslink not in req_names:
1363                             is_exception = False
1364                             for e in dangling_exceptions:
1365                                 if e[0].search(link):
1366                                     is_exception = e[1]
1367                                     break
1368                             if is_exception:
1369                                 if is_exception not in req_names:
1370                                     printWarning(pkg, 'no-dependency-on',
1371                                                  is_exception)
1372                             else:
1373                                 printWarning(pkg, 'dangling-relative-symlink',
1374                                              f, link)
1375                     pathcomponents = f.split('/')[1:]
1376                     r = points_regex.search(link)
1377                     lastpop = None
1378                     mylink = None
1379
1380                     while r:
1381                         mylink = r.group(1)
1382                         if len(pathcomponents) == 0:
1383                             printError(pkg, 'symlink-has-too-many-up-segments',
1384                                        f, link)
1385                             break
1386                         else:
1387                             lastpop = pathcomponents[0]
1388                             pathcomponents = pathcomponents[1:]
1389                             r = points_regex.search(mylink)
1390
1391                     if mylink and lastpop:
1392                         r = absolute2_regex.search(mylink)
1393                         linktop = r.group(1)
1394
1395                         # does the link go up and then down into the same
1396                         # directory?
1397                         #if linktop == lastpop:
1398                         #    printWarning(pkg, 'lengthy-symlink', f, link)
1399
1400                         # have we reached the root directory?
1401                         if len(pathcomponents) == 0 and linktop != lastpop \
1402                                 and not use_relative_symlinks:
1403                             # relative link into other toplevel directory
1404                             printWarning(pkg, 'symlink-should-be-absolute', f,
1405                                          link)
1406                         # check additional segments for mistakes like
1407                         # `foo/../bar/'
1408                         for linksegment in mylink.split('/'):
1409                             if linksegment == '..':
1410                                 printError(
1411                                     pkg,
1412                                     'symlink-contains-up-and-down-segments',
1413                                     f, link)
1414
1415             if f.startswith('/etc/cron.d/'):
1416                 if stat.S_ISLNK(mode):
1417                     printError(pkg, 'symlink-crontab-file', f)
1418
1419                 if mode & 0111:
1420                     printError(pkg, 'executable-crontab-file', f)
1421
1422                 if stat.S_IWGRP & mode or stat.S_IWOTH & mode:
1423                     printError(pkg, 'non-owner-writeable-only-crontab-file', f)
1424
1425         if log_file and not logrotate_file:
1426             printWarning(pkg, 'log-files-without-logrotate', log_file)
1427
1428         if lib_package and lib_file and non_lib_file:
1429             printError(pkg, 'outside-libdir-files', non_lib_file)
1430
1431         if debuginfo_package and debuginfo_debugs and not debuginfo_srcs:
1432             printError(pkg, 'debuginfo-without-sources')
1433
1434         for exe, paths in bindir_exes.items():
1435             if len(paths) > 1:
1436                 printWarning(pkg, "duplicate-executable", exe, paths)
1437             if exe not in man_basenames:
1438                 printWarning(pkg, "no-manual-page-for-binary", exe)
1439
1440 # Create an object to enable the auto registration of the test
1441 check = FilesCheck()
1442
1443 addDetails(
1444 'no-documentation',
1445 '''The package contains no documentation (README, doc, etc).
1446 You have to include documentation files.''',
1447
1448 'not-listed-as-documentation',
1449 '''The documentation files of this package are not listed with
1450 the standard %doc tag.''',
1451
1452 'non-standard-uid',
1453 '''A file in this package is owned by a non standard user.
1454 Standard users are:
1455 %s.''' % ", ".join(standard_users),
1456
1457 'non-standard-gid',
1458 '''A file in this package is owned by a non standard group.
1459 Standard groups are:
1460 %s.''' % ", ".join(standard_groups),
1461
1462 'library-without-ldconfig-postin',
1463 '''This package contains a library and provides no %post scriptlet containing
1464 a call to ldconfig.''',
1465
1466 'postin-without-ldconfig',
1467 '''This package contains a library and its %post scriptlet doesn't call
1468 ldconfig.''',
1469
1470 'library-without-ldconfig-postun',
1471 '''This package contains a library and provides no %postun scriptlet containing
1472 a call to ldconfig.''',
1473
1474 'postun-without-ldconfig',
1475 '''This package contains a library and its %postun doesn't call ldconfig.''',
1476
1477 'info-files-without-install-info-postin',
1478 '''This package contains info files and provides no %post scriptlet containing
1479 a call to install-info.''',
1480
1481 'postin-without-install-info',
1482 '''This package contains info files and its %post doesn't call install-info.''',
1483
1484 'info-files-without-install-info-postun',
1485 '''This package contains info files and provides no %postun scriptlet containing
1486 a call to install-info.''',
1487
1488 'postun-without-install-info',
1489 '''This package contains info files and its %postun doesn't call
1490 install-info.''',
1491
1492 'perl-temp-file',
1493 '''You have a perl temporary file in your package. Usually, this
1494 file is beginning with a dot (.) and contain "perl" in its name.''',
1495
1496 'dir-or-file-in-tmp',
1497 '''A file in the package is located in /tmp. It's not permitted
1498 for packages to install files in this directory.''',
1499
1500 'dir-or-file-in-mnt',
1501 '''A file in the package is located in /mnt. It's not permitted
1502 for packages to install files in this directory.''',
1503
1504 'dir-or-file-in-opt',
1505 '''A file in the package is located in /opt. It's not permitted
1506 for packages to install files in this directory.''',
1507
1508 'dir-or-file-in-usr-local',
1509 '''A file in the package is located in /usr/local. It's not permitted
1510 for packages to install files in this directory.''',
1511
1512 'dir-or-file-in-var-local',
1513 '''A file in the package is located in /var/local. It's not permitted
1514 for packages to install files in this directory.''',
1515
1516 'non-ghost-in-var-run',
1517 '''A file or directory in the package is located in /var/run. Files installed
1518 in this directory should be marked as %ghost and created at runtime to work
1519 properly in tmpfs /var/run setups.''',
1520
1521 'non-ghost-in-var-lock',
1522 '''A file or directory in the package is located in /var/lock. Files installed
1523 in this directory should be marked as %ghost and created at runtime to work
1524 properly in tmpfs /var/lock setups.''',
1525
1526 'subdir-in-bin',
1527 '''The package contains a subdirectory in /usr/bin. It's not permitted to
1528 create a subdir there. Create it in /usr/lib/ instead.''',
1529
1530 'backup-file-in-package',
1531 '''You have a file whose name looks like one for backup files, usually created
1532 by an editor or resulting from applying unclean (fuzzy, or ones with line
1533 offsets) patches.''',
1534
1535 'dir-or-file-in-home',
1536 '''A file in the package is located in /home. It's not permitted
1537 for packages to install files in this directory.''',
1538
1539 'version-control-internal-file',
1540 '''You have included file(s) internally used by a version control system
1541 in the package. Move these files out of the package and rebuild it.''',
1542
1543 'htaccess-file',
1544 '''You have individual apache configuration .htaccess file(s) in your package.
1545 Replace them by a central configuration file in /etc/, according to the web
1546 application packaging policy for your distribution.''',
1547
1548 'info-dir-file',
1549 '''You have /usr/info/dir or /usr/share/info/dir in your package. It will cause
1550 conflicts with other packages and thus is not allowed. Please remove it and
1551 rebuild your package.''',
1552
1553 'non-conffile-in-etc',
1554 '''A non-executable file in your package is being installed in /etc, but is not
1555 a configuration file. All non-executable files in /etc should be configuration
1556 files. Mark the file as %config in the spec file.''',
1557
1558 'compressed-symlink-with-wrong-ext',
1559 '''The symlink points to a compressed file but doesn't use the same
1560 extension.''',
1561
1562 'setuid-binary',
1563 '''The file is setuid; this may be dangerous, especially if this
1564 file is setuid root. Sometimes file capabilities can be used instead of
1565 setuid bits.''',
1566
1567 'setgid-binary',
1568 '''The file is setgid. Usually this is a packaging bug. If this is a game,
1569 then, you should use the proper rpm group, or location.''',
1570
1571 'non-standard-executable-perm',
1572 '''A standard executable should have permission set to 0755. If you get this
1573 message, it means that you have a wrong executable permissions in some files
1574 included in your package.''',
1575
1576 'non-executable-in-bin',
1577 '''A file is being installed in /usr/bin, but is not an executable. Be sure
1578 that the file is an executable or that it has executable permissions.''',
1579
1580 'devel-file-in-non-devel-package',
1581 '''A development file (usually source code) is located in a non-devel
1582 package. If you want to include source code in your package, be sure to
1583 create a development package.''',
1584
1585 'non-standard-dir-perm',
1586 '''A standard directory should have permission set to 0755. If you get this
1587 message, it means that you have wrong directory permissions in some dirs
1588 included in your package.''',
1589
1590 'spurious-executable-perm',
1591 '''The file is installed with executable permissions, but was identified as one
1592 that probably should not be executable.  Verify if the executable bits are
1593 desired, and remove if not.
1594 NOTE: example scripts should be packaged under %docdir/examples, which will avoid
1595 this warning.
1596 ''',
1597
1598 'world-writable',
1599 '''A file or directory in the package is installed with world writable
1600 permissions, which is most likely a security issue.''',
1601
1602 'standard-dir-owned-by-package',
1603 '''This package owns a directory that is part of the standard hierarchy, which
1604 can lead to default directory permissions or ownerships being changed to
1605 something non-standard.''',
1606
1607 'no-dependency-on',
1608 '''
1609 ''',
1610
1611 'cross-directory-hard-link',
1612 '''File is hard linked across directories.  This can cause problems in
1613 installations where the directories are located on different devices.''',
1614
1615 'dangling-symlink',
1616 '''The target of the symbolic link does not exist within this package or its
1617 file based dependencies.  Verify spelling of the link target and that the
1618 target is included in a package in this package's dependency chain.''',
1619
1620 'symlink-should-be-relative',
1621 '''Absolute symlinks are problematic eg. when working with chroot environments.
1622 symlinks(8) is a tool that can be useful for creating/dealing with relative
1623 symlinks at package build time.''',
1624
1625 'dangling-relative-symlink',
1626 '''The target of the symbolic link does not exist within this package or its
1627 file based dependencies.  Verify spelling of the link target and that the
1628 target is included in a package in this package's dependency chain.''',
1629
1630 'symlink-has-too-many-up-segments',
1631 '''
1632 ''',
1633
1634 'symlink-should-be-absolute',
1635 '''
1636 ''',
1637
1638 'symlink-contains-up-and-down-segments',
1639 '''
1640 ''',
1641
1642 'non-readable',
1643 '''The file can't be read by everybody. If this is expected (for security
1644 reasons), contact your rpmlint distributor to get it added to the list of
1645 exceptions for your distro (or add it to your local configuration if you
1646 installed rpmlint from the source tarball).''',
1647
1648 'incoherent-logrotate-file',
1649 '''Your logrotate file should be named /etc/logrotate.d/<package name>.''',
1650
1651 'non-root-user-log-file',
1652 '''If you need log files owned by a non-root user, just create a subdir in
1653 /var/log and put your log files in it.''',
1654
1655 'non-root-group-log-file',
1656 '''If you need log files owned by a non-root group, just create a subdir in
1657 /var/log and put your log files in it.''',
1658
1659 'non-ghost-file',
1660 '''File should be tagged %ghost.''',
1661
1662 'outside-libdir-files',
1663 '''This library package must not contain non library files to allow 64
1664 and 32 bits versions of the package to coexist.''',
1665
1666 'hidden-file-or-dir',
1667 '''The file or directory is hidden. You should see if this is normal,
1668 and delete it from the package if not.''',
1669
1670 'module-without-depmod-postin',
1671 '''This package contains a kernel module but provides no call to depmod in the
1672 %post scriptlet.''',
1673
1674 'postin-with-wrong-depmod',
1675 '''This package contains a kernel module but its %post scriptlet calls depmod
1676 for the wrong kernel.''',
1677
1678 'module-without-depmod-postun',
1679 '''This package contains a kernel module but provides no call to depmod in the
1680 %postun scriptlet.''',
1681
1682 'postun-with-wrong-depmod',
1683 '''This package contains a kernel module but its %postun scriptlet calls depmod
1684 for the wrong kernel.''',
1685
1686 'log-files-without-logrotate',
1687 '''This package contains files in /var/log/ without adding logrotate
1688 configuration for them.''',
1689
1690 'unexpanded-macro',
1691 '''This package contains a file whose path contains something that looks like
1692 an unexpanded macro; this is often the sign of a misspelling. Please check your
1693 specfile.''',
1694
1695 'manifest-in-perl-module',
1696 '''This perl module package contains a MANIFEST or a MANIFEST.SKIP file
1697 in the documentation directory.''',
1698
1699 'siteperl-in-perl-module',
1700 '''This perl module package installs files under the subdirectory site_perl,
1701 while they must appear under vendor_perl.''',
1702
1703 'executable-marked-as-config-file',
1704 '''Executables must not be marked as config files because that may
1705 prevent upgrades from working correctly. If you need to be able to
1706 customize an executable, make it for example read a config file in
1707 /etc/sysconfig.''',
1708
1709 'sourced-script-with-shebang',
1710 '''This text file contains a shebang, but is meant to be sourced, not
1711 executed.''',
1712
1713 'executable-sourced-script',
1714 '''This text file has executable bit set, but is meant to be sourced, not
1715 executed.''',
1716
1717 'wrong-script-interpreter',
1718 '''This script uses an incorrect interpreter. Correct interpreters should
1719 be an absolute path to a file in in /(s)bin or /usr/(s)bin.
1720 Alternatively, if the file isn't supposed to be executed, then don't
1721 mark it as executable.  ''',
1722
1723 'non-executable-script',
1724 '''This text file contains a shebang or is located in a path dedicated for
1725 executables, but lacks the executable bits and cannot thus be executed.  If
1726 the file is meant to be an executable script, add the executable bits,
1727 otherwise remove the shebang or move the file elsewhere.''',
1728
1729 'script-without-shebang',
1730 '''This text file has executable bits set or is located in a path dedicated
1731 for executables, but lacks a shebang and cannot thus be executed.  If the file
1732 is meant to be an executable script, add the shebang, otherwise remove the
1733 executable bits or move the file elsewhere.''',
1734
1735 'wrong-script-end-of-line-encoding',
1736 '''This script has wrong end-of-line encoding, usually caused by creation or
1737 modification on a non-Unix system. It will prevent its execution.''',
1738
1739 'wrong-file-end-of-line-encoding',
1740 '''This file has wrong end-of-line encoding, usually caused by creation or
1741 modification on a non-Unix system. It could prevent it from being displayed
1742 correctly in some circumstances.''',
1743
1744 'file-not-utf8',
1745 '''The character encoding of this file is not UTF-8.  Consider converting it
1746 in the specfile's %prep section for example using iconv(1).''',
1747
1748 'filename-not-utf8',
1749 '''The character encoding of the name of this file is not UTF-8.
1750 Rename it.''',
1751
1752 'file-in-meta-package',
1753 '''This package seems to be a meta-package (an empty package used to require
1754 other packages), but it is not empty. You should remove or rename it, see the
1755 option MetaPackageRegexp.''',
1756
1757 'empty-debuginfo-package',
1758 '''This debuginfo package contains no files.  This is often a sign of binaries
1759 being unexpectedly stripped too early during the build, rpmbuild not being able
1760 to strip the binaries, the package actually being a noarch one but erratically
1761 packaged as arch dependent, or something else.  Verify what the case is, and
1762 if there's no way to produce useful debuginfo out of it, disable creation of
1763 the debuginfo package.''',
1764
1765 'debuginfo-without-sources',
1766 '''This debuginfo package appears to contain debug symbols but no source files.
1767 This is often a sign of binaries being unexpectedly stripped too early during
1768 the build, or being compiled without compiler debug flags (which again often
1769 is a sign of distro's default compiler flags ignored which might have security
1770 consequences), or other compiler flags which result in rpmbuild's debuginfo
1771 extraction not working as expected.  Verify that the binaries are not
1772 unexpectedly stripped and that the intended compiler flags are used.''',
1773
1774 'missing-dependency-to-cron',
1775 '''This package installs a file in /etc/cron.*/ but
1776 doesn't require cron to be installed. as cron is not part of the essential packages,
1777 your package should explicitely require cron to make sure that your cron job is
1778 executed. If it is an optional feature of your package, recommend or suggest cron.''',
1779
1780 'missing-dependency-to-logrotate',
1781 '''This package installs a file in /etc/logrotate.d/ but
1782 doesn't require logrotate to be installed. Because logrotate is not part of the essential packages,
1783 your package should explicitely depend on logrotate to make sure that your logrotate
1784 job is executed. If it is an optional feature of your package, recommend or suggest logrotate.''',
1785
1786 'missing-dependency-to-xinetd',
1787 '''This package installs a file in /etc/xinetd.d/ but
1788 doesn't require xinetd to be installed. Because xinetd is not part of the essential packages,
1789 your package should explicitely depend on logrotate to make sure that your xinetd
1790 job is executed. If it is an optional feature of your package, recommend or suggest xinetd.''',
1791
1792 'read-error',
1793 '''This file could not be read.  A reason for this could be that the info about
1794 it in the rpm header indicates that it is supposed to be a readable normal file
1795 but it actually is not in the filesystem.  Because of this, some checks will
1796 be skipped.''',
1797
1798 'executable-crontab-file',
1799 '''This crontab file has executable bit set, which is refused by newer version
1800 of cron''',
1801
1802 'non-owner-writeable-only-crontab-file',
1803 '''This crontab file is writeable by other users as its owner, which is refused
1804 by newer version of cron and insecure''',
1805
1806 'symlink-crontab-file',
1807 '''This crontab file is a symbolic link, which is insecure and refused by newer
1808 version of cron''',
1809
1810 'rpath-in-buildconfig',
1811 '''This build configuration file contains rpaths which will be introduced into
1812 dependent packages.''',
1813
1814 'python-bytecode-wrong-magic-value',
1815 '''The "magic" ABI version embedded in this python bytecode file isn't equal
1816 to that of the corresponding runtime, which will force the interpreter to
1817 recompile the .py source every time, ignoring the saved bytecode.''',
1818
1819 'python-bytecode-inconsistent-mtime',
1820 '''The timestamp embedded in this python bytecode file isn't equal to the mtime
1821 of the original source file, which will force the interpreter to recompile the
1822 .py source every time, ignoring the saved bytecode.''',
1823
1824 'python-bytecode-without-source',
1825 '''This python bytecode file (.pyo/.pyc) is not accompanied by its original
1826 source file (.py)''',
1827
1828 'duplicate-executable',
1829 '''This executable file exists in more than one standard binary directories.
1830 It can cause problems when dirs in $PATH are reordered.''',
1831
1832 'no-manual-page-for-binary',
1833 '''Each executable in standard binary directories should have a man page.''',
1834
1835 'manual-page-warning',
1836 '''This man page may contain problems that can cause it not to be formatted
1837 as intended.''',
1838
1839 'incorrect-fsf-address',
1840 '''The Free Software Foundation address in this file seems to be outdated or
1841 misspelled.  Ask upstream to update the address, or if this is a license file,
1842 possibly the entire file with a new copy available from the FSF.''',
1843 )
1844
1845 # FilesCheck.py ends here
1846
1847 # Local variables:
1848 # indent-tabs-mode: nil
1849 # py-indent-offset: 4
1850 # End:
1851 # ex: ts=4 sw=4 et