aboutsummaryrefslogtreecommitdiff
path: root/sbopkglint.d/30-manpages.t.sh
blob: af8ab0a527919c8d68c8b9878da602d64ebd7a7a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/bin/sh

# sbopkglint test, must be sourced by sbopkglint (not run standalone).

# PKG, PRGNAM, VERSION, ARCH are set by sbopkglint. also the current
# directory is the root of the installed package tree.

#######################################################################
# if the package contains the usr/man dir, make sure that:
# all the dirs match usr/man/man[1-9n] or usr/man/<locale>/man[1-9n].
# all the files under /usr/man are gzipped and end in <section>.gz.
# all the files under /usr/man have mode 0644. executable man pages
# don't make sense, and man pages that aren't world-readable are
# annoying and wrong.
# all the filenames match the sections (e.g. usr/man/man1/foo.1.gz
# matches, usr/man/man1/bar.2.gz doesn't).
# all the gzipped files look like they contain *roff.

BADPERMS=""
BADDIRPERMS=""
BADDIRS=""
BADNAMES=""
NOTGZIPPED=""
NONTROFF=""
WRONGSECT=""

check_gzipped_page() {
	local f="$1"
	local d="$( dirname $f )"
	local s="$( stat -c '%a %U %G' "$f" )"

	if [ "$s" = "444 root root" ]; then
		: # we could warn here someday
	elif [ "$s" != "644 root root" ]; then
		BADPERMS+="$f "
	fi

	is_gzipped "$f" || NOTGZIPPED+="$f "

	# I have ~42,000 man pages on my dev box, file(1) fails to identify
	# 12 of them as troff, but adding the check for .T catches them all.
	if [ "$( file -zS -m /etc/file/magic/troff -L -b --mime-type "$f" )" != "text/troff" ]; then
		if ! zgrep -q '^\.T' "$f"; then
			NONTROFF+="$f "
		fi
	fi

	# checking the section is tricky because e.g. /usr/man/man1 may contain
	# files with with names like .1.gz, .1x.gz, .1.pm.gz.

	# if the section in the directory name is bad, don't complain here, it
	# was already reported.
	dir_s="$( echo "$d" | sed -n 's,.*man\([0-9n]\)$,\1,p' )"
	if [ "$dir_s" = "" ]; then
		return
	fi

	s="$( basename "$f" | sed -n 's,.*\.\([0-9n]\)[^.]*\.gz,\1,p' )"
	if [ "$s" = "" ]; then
		BADNAMES+="$f "
	elif [ "$s" != "$dir_s" ]; then
		WRONGSECT+="$f "
	fi
}

# called for paths like /usr/man/de. right now, it accepts names like
# xx_XX or xx.UTF-8, or actually anything whose first 2 characters match
# one of the dirs in /usr/share/locale. could use some refining.
# these dir names can have an optional country code, and/or optional
# encoding. so all these are valid:
# de de_DE de.UTF-8 de_DE.UTF-8 de.ISO8859-1 de_DE.ISO8859-1
# this code doesn't attempt to validate the country code (e.g. de_JP
# would be "German as written in Japan", there's no such thing), and
# it doesn't attempt to check encodings for existence or even plausibility.
# Note that slackware's own libcdio-paranoia install man pages in
# /usr/man/jp, which is invalid.
check_locale_dir() {
	if [ "$ALL_LOCALES" = "" ]; then
		ALL_LOCALES=$( l=$( locale -a|grep -v '^[A-Z]'|sed 's,[^a-z].*$,,'|sort -u ); echo $l )
	fi

	ldir="$( echo "$1" | cut -d/ -f3 )"
	l="$( echo "$ldir" | sed 's,^\(..\).*,\1,' )"
	if ! echo $ALL_LOCALES | grep -q "\\<$l\\>"; then
		warn "invalid locale '$ldir' in path $1"
	fi
}

if [ -d usr/man ]; then
	find usr/man -name "* *" -print0 | xargs -r0 ls -bld > .spaces.$$
	if [ -s .spaces.$$ ]; then
		warn "/usr/man may not contain filenames with spaces:"
		cat .spaces.$$
	fi
	rm -f .spaces.$$

	# anything with a space in it won't be found by these, but
	# it was complained about already.
	find usr/man -type f -a \! -name "* *" > .manpages.$$
	find usr/man -mindepth 1 -type d -a \! -name "* *" > .mandirs.$$
	find usr/man -type d -a -empty -a \! -name "* *" > .manemptydirs.$$

	while read d; do
		[ "$( stat -c '%a %U %G' "$d" )" != "755 root root" ] && BADDIRPERMS+="$d "
		case "$d" in
			usr/man/*/*/*|usr/man/man[1-9ln]/*|usr/man/man)
				BADDIRS+="$d " ;;
			usr/man/man[1-9n])
				;;
			usr/man/*)
				check_locale_dir "$d"
				;;
			*) BADDIRS+="$d " ;;
		esac
	done < .mandirs.$$

	while read f; do
		case "$f" in
			*.gz) check_gzipped_page "$f" ;;
			*) BADNAMES+="$f " ;;
		esac
	done < .manpages.$$

	if [ -s .manemptydirs.$$ ]; then
		warn "empty dir(s) in /usr/man:"
		cat .manemptydirs.$$
	fi

	rm -f .manpages.$$ .mandirs.$$ .manemptydirs.$$

	[ -n "$BADPERMS" ] && warn "bad man page owner/permissions (should be 0644, root:root)" && ls -ld $BADPERMS
	[ -n "$BADDIRPERMS" ] && warn "bad man directory owner/permissions (should be 0755, root:root)" && ls -ld $BADDIRPERMS
	[ -n "$BADDIRS" ] && warn "bad directory names in /usr/man:" && ls -ld $BADDIRS
	[ -n "$BADNAMES" ] && warn "bad man page names (not *.gz):" && ls -ld $BADNAMES
	[ -n "$NOTGZIPPED" ] && warn "non-gzipped (but named *.gz) man pages:" && ls -ld $NOTGZIPPED
	[ -n "$NONTROFF" ] && warn "invalid man pages (not troff):" && ls -ld $NONTROFF
	[ -n "$WRONGSECT" ] && warn "man pages in wrong section:" && ls -ld $WRONGSECT
fi