Gentoo Archives: gentoo-commits

From: Michael Palimaka <kensington@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/qa-scripts:master commit in: /
Date: Sun, 08 Jun 2014 16:23:50
Message-Id: 1402244606.29ece55c0c90b5bbe8ab21ddd6e0363ea9bd053a.kensington@gentoo
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