1 |
commit: 29ece55c0c90b5bbe8ab21ddd6e0363ea9bd053a |
2 |
Author: Michael Palimaka <kensington <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sun Jun 8 16:23:26 2014 +0000 |
4 |
Commit: Michael Palimaka <kensington <AT> gentoo <DOT> org> |
5 |
CommitDate: Sun Jun 8 16:23:26 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/qa-scripts.git;a=commit;h=29ece55c |
7 |
|
8 |
depcheck: add script for checking binary runtime dependencies. |
9 |
|
10 |
--- |
11 |
depcheck | 258 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
12 |
1 file changed, 258 insertions(+) |
13 |
|
14 |
diff --git a/depcheck b/depcheck |
15 |
new file mode 100755 |
16 |
index 0000000..15e171e |
17 |
--- /dev/null |
18 |
+++ b/depcheck |
19 |
@@ -0,0 +1,258 @@ |
20 |
+#!/bin/bash |
21 |
+# |
22 |
+# Copyright (c) 2014 Michael Palimaka <kensington@g.o> |
23 |
+# |
24 |
+# Permission is hereby granted, free of charge, to any person obtaining a copy |
25 |
+# of this software and associated documentation files (the "Software"), to deal |
26 |
+# in the Software without restriction, including without limitation the rights |
27 |
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
28 |
+# copies of the Software, and to permit persons to whom the Software is |
29 |
+# furnished to do so, subject to the following conditions: |
30 |
+# |
31 |
+# The above copyright notice and this permission notice shall be included in |
32 |
+# all copies or substantial portions of the Software. |
33 |
+# |
34 |
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
35 |
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
36 |
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
37 |
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
38 |
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
39 |
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
40 |
+# THE SOFTWARE. |
41 |
+# |
42 |
+# A tool to report both undeclared and potentially-unused runtime dependencies. |
43 |
+# |
44 |
+# Depends on app-misc/pax-utils, app-portage/portage-utils and |
45 |
+# sys-apps/gentoo-functions. |
46 |
+ |
47 |
+DEBUG=FALSE |
48 |
+IGNORE_DEPS=( "sys-libs/glibc" "sys-devel/gcc" ) |
49 |
+IGNORE_LINKS=( "/lib64/libgcc_s.so.1" ) |
50 |
+PKG_DIR="/var/db/pkg/" |
51 |
+ |
52 |
+. /lib/gentoo/functions.sh |
53 |
+ |
54 |
+bold() { |
55 |
+ echo $@ |
56 |
+ return |
57 |
+ local bold=$(tput bold) |
58 |
+ local normal=$(tput sgr0) |
59 |
+ echo "${bold}${@}${normal}" |
60 |
+} |
61 |
+ |
62 |
+debug() { |
63 |
+ if [ $DEBUG = TRUE ]; then |
64 |
+ # write to stderr so as not to interfere with function returns |
65 |
+ echo "$@" 1>&2 |
66 |
+ fi |
67 |
+} |
68 |
+ |
69 |
+# app-foo/bar-1.2.3-r1 -> app-foo/bar |
70 |
+remove_atom_version() { |
71 |
+ local atom=`qatom "${1}" | cut -d " " -f 1-2 | tr " " /` |
72 |
+ echo $atom |
73 |
+} |
74 |
+ |
75 |
+check_atom() { |
76 |
+ |
77 |
+ local errors=0 |
78 |
+ local atom=$1 |
79 |
+ local checked=() |
80 |
+ local rdepends=() |
81 |
+ |
82 |
+ local objects=`qlist -qo ${atom}` |
83 |
+ |
84 |
+ if [ ! "${objects}" ]; then |
85 |
+ einfo ${atom} does not have any objects installed, skipping... |
86 |
+ echo |
87 |
+ return |
88 |
+ fi |
89 |
+ |
90 |
+ einfo Checking ${atom} for undeclared dependencies |
91 |
+ eindent |
92 |
+ |
93 |
+ local obj |
94 |
+ for obj in $objects |
95 |
+ do |
96 |
+ debug "Checking ${obj}" |
97 |
+ |
98 |
+ readelf -h ${obj} > /dev/null 2>&1 |
99 |
+ |
100 |
+ # can it have stuff linked to it? |
101 |
+ if [ $? -ne 0 ]; then |
102 |
+ debug "It can't have links, skipping" |
103 |
+ continue |
104 |
+ fi |
105 |
+ |
106 |
+ local elf=`scanelf --format "#f%n" --nobanner --use-ldpath ${obj} 2>&1` |
107 |
+ local links=`echo ${elf} | tr "," " "` |
108 |
+ |
109 |
+ # get a list of everything that it's linked to |
110 |
+ local link |
111 |
+ for link in $links |
112 |
+ do |
113 |
+ local ignore |
114 |
+ for ignore in "${IGNORE_LINKS[@]}"; do |
115 |
+ if [ "${ignore}" = "${link}" ]; then |
116 |
+ debug "Ignoring ${link} due to blacklist" |
117 |
+ continue 2 |
118 |
+ fi |
119 |
+ done |
120 |
+ |
121 |
+ # only check a library once per atom for performance reasons |
122 |
+ local check |
123 |
+ for check in "${checked[@]}"; do |
124 |
+ if [ "${check}" = "${link}" ]; then |
125 |
+ debug "Already checked ${link} for this atom, skipping" |
126 |
+ continue 2 |
127 |
+ fi |
128 |
+ done |
129 |
+ |
130 |
+ checked=( "${checked[@]}" "${link}" ) |
131 |
+ |
132 |
+ debug "Found ${link}" |
133 |
+ |
134 |
+ local libowner=`qfile -vqC ${link} | uniq` |
135 |
+ |
136 |
+ if [ ! "${libowner}" ]; then |
137 |
+ ewarn "No package claims ${link} (${obj})" |
138 |
+ continue |
139 |
+ fi |
140 |
+ |
141 |
+ debug "Owning package for ${link} is ${libowner}" |
142 |
+ |
143 |
+ local libowner_pn=$(remove_atom_version ${libowner}) |
144 |
+ local my_pn=$(remove_atom_version ${atom}) |
145 |
+ |
146 |
+ rdepends+=( "${libowner_pn}" ) |
147 |
+ |
148 |
+ if [ "${libowner_pn}" = "${my_pn}" ]; then |
149 |
+ debug "Owning package is self, ignoring" |
150 |
+ continue |
151 |
+ fi |
152 |
+ |
153 |
+ local ignorelib |
154 |
+ for ignorelib in "${IGNORE_DEPS[@]}" |
155 |
+ do |
156 |
+ if [ "${libowner_pn}" = "${ignorelib}" ]; then |
157 |
+ debug "Ignoring objects belonging to ${ignorelib}" |
158 |
+ continue 2 |
159 |
+ fi |
160 |
+ done |
161 |
+ |
162 |
+ debug "Checking if ${libowner_pn} is in the RDEPEND list of ${atom}" |
163 |
+ |
164 |
+ local isdep |
165 |
+ isdep=`qdepends -r ${atom} | grep ${libowner_pn}` |
166 |
+ |
167 |
+ if [ $? -ne 0 ]; then |
168 |
+ eerror "${obj} links to ${link}" |
169 |
+ eindent |
170 |
+ eerror Missing dependency on $(bold ${libowner_pn}) |
171 |
+ eoutdent |
172 |
+ errors=1 |
173 |
+ fi |
174 |
+ |
175 |
+ |
176 |
+ done |
177 |
+ |
178 |
+ done |
179 |
+ |
180 |
+ local ebuild_rdepends=() |
181 |
+ for rdepend in $(qdepends --nocolor --quiet --rdepend ${atom} | sed -e "s/\[[^]]*\]//g" | cut -d : -f 2-) |
182 |
+ do |
183 |
+ ebuild_rdepends+=( $(remove_atom_version $rdepend) ) |
184 |
+ done |
185 |
+ |
186 |
+ debug "Ebuild RDEPENDS: ${ebuild_rdepends[@]}" |
187 |
+ debug "Linked RDEPENDS: ${rdepends[@]}" |
188 |
+ |
189 |
+ local suspect_rdepends=$(comm -13 <(echo ${rdepends[@]} | sed 's/ /\n/g' | sort -u) <(echo ${ebuild_rdepends[@]} | sed 's/ /\n/g' | sort -u)) |
190 |
+ if [ "${suspect_rdepends}" ]; then |
191 |
+ ewarn "Suspect RDEPEND: $(bold ${suspect_rdepends})" |
192 |
+ fi |
193 |
+ |
194 |
+ echo |
195 |
+ eoutdent |
196 |
+ |
197 |
+ return $errors |
198 |
+ |
199 |
+} |
200 |
+ |
201 |
+check_package() { |
202 |
+ |
203 |
+ local package=$1 |
204 |
+ local atoms=`qlist -IcCS ${package} | tr ' ' '-' | cut -d : -f1` |
205 |
+ |
206 |
+ debug Package ${package} own atoms: ${atoms} |
207 |
+ |
208 |
+ if [ ! "${atoms}" ]; then |
209 |
+ eerror ERROR: ${package} is not a valid atom |
210 |
+ exit 1 |
211 |
+ fi |
212 |
+ |
213 |
+ for atom in ${atoms}; do |
214 |
+ check_atom ${atom} |
215 |
+ done |
216 |
+ |
217 |
+} |
218 |
+ |
219 |
+check_category() { |
220 |
+ |
221 |
+ local errors=0 |
222 |
+ |
223 |
+ for package in `ls "${PKG_DIR}/${1}"`; do |
224 |
+ |
225 |
+ check_package "${1}/${package}" |
226 |
+ |
227 |
+ if [ $? -ne 0 ]; then |
228 |
+ errors=1 |
229 |
+ fi |
230 |
+ |
231 |
+ done; |
232 |
+ |
233 |
+ return $errors |
234 |
+ |
235 |
+} |
236 |
+ |
237 |
+BINNAME=`basename ${0}` |
238 |
+if [ -z $1 ]; then |
239 |
+ echo "Checks emerged package(s) for undeclared depedencies" |
240 |
+ echo |
241 |
+ echo "Usage: ${BINNAME} [ atom | -c category | -a ]" |
242 |
+ echo |
243 |
+ echo "Examples:" |
244 |
+ echo "Check a single package: ${BINNAME} app-foo/bar-1.2.3" |
245 |
+ echo "Check a category: ${BINNAME} -c app-foo" |
246 |
+ echo "Check everything: ${BINNAME} -a" |
247 |
+ exit 1 |
248 |
+fi |
249 |
+ |
250 |
+# check a particular category |
251 |
+if [ "$1" = "-c" ]; then |
252 |
+ |
253 |
+ CAT=$2 |
254 |
+ |
255 |
+ if [ ! -d "${PKG_DIR}/${CAT}" ]; then |
256 |
+ eerror ERROR: No packages from the category ${CAT} have been emerged yet |
257 |
+ exit 1 |
258 |
+ fi |
259 |
+ |
260 |
+ check_category $CAT |
261 |
+ |
262 |
+# check everything |
263 |
+elif [ "$1" = "-a" ]; then |
264 |
+ |
265 |
+ for category in `ls ${PKG_DIR}`; do |
266 |
+ check_category $category |
267 |
+ done; |
268 |
+ |
269 |
+else |
270 |
+ check_package $1 |
271 |
+fi |
272 |
+ |
273 |
+if [ $? -eq 0 ]; then |
274 |
+ einfo Checking complete, no errors found |
275 |
+else |
276 |
+ eerror Checking complete, errors found |
277 |
+fi |