aboutsummaryrefslogtreecommitdiff
path: root/sbopkglint.d/05-basic-sanity.t.sh
blob: 6709203db7272469141d5c8d9674e3ee4d179432 (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
140
141
142
143
144
145
146
147
148
149
150
151
152
#!/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.

#######################################################################
# these directories are allowed to exist in the package, but they
# must be mode 0755 and owned by root:root. if a dir from this list
# exists but is empty, that's an error. if a top-level directory
# exists that's *not* in this list (such as /dev), that's an error.
topleveldirs="bin boot etc lib lib64 opt sbin srv usr var run"

# these directories are *required* to exist, and must be mode 0755, root:root.
# if a dir from this list exists but is empty, that's an error. note
# that the install/ dir no longer exists by the time we run (installpkg
# deleted it already).
requireddirs="usr/doc/$PRGNAM-$VERSION"

# these directories *must not* exist. no need to list top-level dirs here,
# the topleveldirs check already catches those.
baddirs="usr/local usr/share/doc usr/share/man usr/etc usr/share/info usr/X11 usr/X11R6"

# these directories may exist, but must contain only files or symlinks,
# and must be mode 0755, root:root. I thought usr/share/pixmaps
# belonged here, but quite a few packages create subdirs there for
# images required at runtime that aren't the app icon.
fileonlydirs="bin usr/bin sbin usr/sbin"

# these directories may exist, but must contain only subdirectories
# (no files, symlinks, devices, etc). "." (the top-level package dir)
# doesn't need to be included here; it's checked separately.
nofiledirs="usr usr/doc usr/share usr/man"

# these directories may exist but must not have executable files
# anywhere under them. I would put usr/doc and etc here, but too many
# packages break that rule. usr/share/applications is listed here,
# even though Slackware's KDE packages (erroneously) install .desktop
# files +x.
noexecdirs="usr/man usr/share/pixmaps usr/share/icons usr/share/applications usr/share/appdata usr/share/mime usr/share/mime-info usr/share/glib-2.0"

# these files must exist.
requiredfiles="usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild"

# these files must not exist.
badfiles="\
usr/info/dir \
usr/info/dir.gz \
usr/lib64/perl5/perllocal.pod \
usr/lib/perl5/perllocal.pod \
usr/share/perl5/perllocal.pod \
usr/share/perl5/vendor_perl/perllocal.pod \
etc/passwd \
etc/passwd.new \
etc/shadow \
etc/shadow.new \
etc/group \
etc/group.new \
etc/gshadow \
etc/gshadow.new \
etc/ld.so.conf"

#######################################################################

# include 'hidden' files/dirs in * wildcard expansion.
shopt -s dotglob

dir_ok() {
	[ -d "$1" ] && \
		[ "$( stat -c '%A %U %G' "$1" )" = "drwxr-xr-x root root" ]
}

dir_empty() {
	[ "$( find "$1" -mindepth 1 -maxdepth 1 )" = "" ]
}

warn_badperms() {
	warn "bad permissions/owner (should be 0755 root:root): $1"
}

for i in *; do
	if [ ! -d "$i" ]; then
		warn "package root dir contains non-directory: $i"
	elif ! echo "$topleveldirs" | grep -q "\\<$i\\>"; then
		warn "package root dir contains non-standard directory: $i"
	elif ! dir_ok "$i"; then
		warn_badperms "$i"
	elif dir_empty "$i"; then
		warn "package contains empty top-level directory: $i"
	fi
done

for i in $requireddirs; do
	if [ ! -d "$i" ]; then
		warn "missing required directory: $i"
	elif ! dir_ok "$i"; then
		warn_badperms "$i"
	fi
done

for i in $baddirs; do
	if [ -d "$i" ]; then
		warn "forbidden directory exists: $i"
	elif [ -e "$i" ]; then
		warn "forbidden directory exists as a non-directory: $i"
	fi
done

for i in $fileonlydirs; do
	[ -d "$i" ] || continue
	dir_ok "$i" || warn_badperms "$i"
	badstuff="$( find -L "$i" -mindepth 1 -maxdepth 1 \! -type f )"
	[ -n "$badstuff" ] && warn "$i should only contain files, not:" && ls -ld $badstuff
done

for i in $nofiledirs; do
	[ -d "$i" ] || continue
	dir_ok "$i" || warn_badperms "$i"
	badstuff="$( find -L "$i" -mindepth 1 -maxdepth 1 \! -type d )"
	[ -n "$badstuff" ] && warn "$i should only contain directories, not:" && ls -ld $badstuff
done

for i in $requiredfiles; do
	[ -f "$i" ] || warn "missing required file: $i"
done

for i in $noexecdirs; do
	[ -d "$i" ] || continue
	found="$( find "$i" -type f -a -perm /0111 )"
	if [ -n "$found" ]; then
		warn "$i should not contain files with executable permission:"
		ls -l $found
	fi
done

for i in $badfiles; do
	[ -e "$i" ] && warn "forbidden file: $i"
done

badlinks="$( find -L . -type l )"
[ -n "$badlinks" ] && for i in $badlinks; do
	target="$( readlink "$i" )"
	case "$target" in
		/*) abslinks+="$i " ;;
		*) brokenlinks+="$i " ;;
	esac
done

[ -n "$abslinks" ] && warn "package contains absolute symlinks (should be relative):" && ls -ld $abslinks
[ -n "$brokenlinks" ] && warn "package contains broken symlinks:" && ls -ld $brokenlinks