aboutsummaryrefslogtreecommitdiff
path: root/sbopkglint.d/30-manpages.t.sh
blob: 30c3841afe1d3c34d8c54cc65c9d698ab1a17b24 (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
#!/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

	if [ "$( file -L -b --mime-type "$f" )" != "application/gzip" ]; then
		NOTGZIPPED+="$f "
	fi

	# 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 -z -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 -type f > .manpages.$$
	find usr/man -mindepth 1 -type d > .mandirs.$$

	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.$$

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

	[ -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-gzip (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