1 |
#!/bin/sh |
2 |
|
3 |
# NAME: |
4 |
# meta2deps.sh - extract useful info from .meta files |
5 |
# |
6 |
# SYNOPSIS: |
7 |
# meta2deps.sh SB="SB" "meta" ... |
8 |
# |
9 |
# DESCRIPTION: |
10 |
# This script looks each "meta" file and extracts the |
11 |
# information needed to deduce build and src dependencies. |
12 |
# |
13 |
# To do this, we extract the 'CWD' record as well as all the |
14 |
# syscall traces which describe 'R'ead, 'C'hdir and 'E'xec |
15 |
# syscalls. |
16 |
# |
17 |
# The typical meta file looks like:: |
18 |
#.nf |
19 |
# |
20 |
# # Meta data file "path" |
21 |
# CMD "command-line" |
22 |
# CWD "cwd" |
23 |
# TARGET "target" |
24 |
# -- command output -- |
25 |
# -- filemon acquired metadata -- |
26 |
# # buildmon version 2 |
27 |
# V 2 |
28 |
# E "pid" "path" |
29 |
# R "pid" "path" |
30 |
# C "pid" "cwd" |
31 |
# R "pid" "path" |
32 |
# X "pid" "status" |
33 |
#.fi |
34 |
# |
35 |
# The fact that all the syscall entry lines start with a single |
36 |
# character make these files quite easy to process using sed(1). |
37 |
# |
38 |
# To simplify the logic the 'CWD' line is made to look like a |
39 |
# normal 'C'hdir entry, and "cwd" is remembered so that it can |
40 |
# be prefixed to any "path" which is not absolute. |
41 |
# |
42 |
# If the "path" being read ends in '.srcrel' it is the content |
43 |
# of (actually the first line of) that file that we are |
44 |
# interested in. |
45 |
# |
46 |
# Any "path" which lies outside of the sandbox "SB" is generally |
47 |
# not of interest and is ignored. |
48 |
# |
49 |
# The output, is a set of absolute paths with "SB" like: |
50 |
#.nf |
51 |
# |
52 |
# $SB/obj-i386/bsd/gnu/lib/csu |
53 |
# $SB/obj-i386/bsd/gnu/lib/libgcc |
54 |
# $SB/obj-i386/bsd/include |
55 |
# $SB/obj-i386/bsd/lib/csu/i386 |
56 |
# $SB/obj-i386/bsd/lib/libc |
57 |
# $SB/src/bsd/include |
58 |
# $SB/src/bsd/sys/i386/include |
59 |
# $SB/src/bsd/sys/sys |
60 |
# $SB/src/pan-release/rtsock |
61 |
# $SB/src/pfe-shared/include/jnx |
62 |
#.fi |
63 |
# |
64 |
# Which can then be further processed by 'gendirdeps.mk' |
65 |
# |
66 |
# If we are passed 'DPDEPS='"dpdeps", then for each src file |
67 |
# outside of "CURDIR" we read, we output a line like: |
68 |
#.nf |
69 |
# |
70 |
# DPDEPS_$path += $RELDIR |
71 |
#.fi |
72 |
# |
73 |
# with "$path" geting turned into reldir's, so that we can end |
74 |
# up with a list of all the directories which depend on each src |
75 |
# file in another directory. This can allow for efficient yet |
76 |
# complete testing of changes. |
77 |
|
78 |
|
79 |
# RCSid: |
80 |
# $Id: meta2deps.sh,v 1.12 2016/12/13 20:44:16 sjg Exp $ |
81 |
|
82 |
# Copyright (c) 2010-2013, Juniper Networks, Inc. |
83 |
# All rights reserved. |
84 |
# |
85 |
# Redistribution and use in source and binary forms, with or without |
86 |
# modification, are permitted provided that the following conditions |
87 |
# are met: |
88 |
# 1. Redistributions of source code must retain the above copyright |
89 |
# notice, this list of conditions and the following disclaimer. |
90 |
# 2. Redistributions in binary form must reproduce the above copyright |
91 |
# notice, this list of conditions and the following disclaimer in the |
92 |
# documentation and/or other materials provided with the distribution. |
93 |
# |
94 |
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
95 |
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
96 |
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
97 |
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
98 |
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
99 |
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
100 |
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
101 |
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
102 |
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
103 |
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
104 |
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
105 |
|
106 |
meta2src() { |
107 |
cat /dev/null "$@" | |
108 |
sed -n '/^R .*\.[chyl]$/s,^..[0-9]* ,,p' | |
109 |
sort -u |
110 |
} |
111 |
|
112 |
meta2dirs() { |
113 |
cat /dev/null "$@" | |
114 |
sed -n '/^R .*\/.*\.[a-z0-9][^\/]*$/s,^..[0-9]* \(.*\)/[^/]*$,\1,p' | |
115 |
sort -u |
116 |
} |
117 |
|
118 |
add_list() { |
119 |
sep=' ' |
120 |
suffix= |
121 |
while : |
122 |
do |
123 |
case "$1" in |
124 |
"|") sep="$1"; shift;; |
125 |
-s) suffix="$2"; shift 2;; |
126 |
*) break;; |
127 |
esac |
128 |
done |
129 |
name=$1 |
130 |
shift |
131 |
eval list="\$$name" |
132 |
for top in "$@" |
133 |
do |
134 |
case "$sep$list$sep" in |
135 |
*"$sep$top$suffix$sep"*) continue;; |
136 |
esac |
137 |
list="${list:+$list$sep}$top$suffix" |
138 |
done |
139 |
eval "$name=\"$list\"" |
140 |
} |
141 |
|
142 |
_excludes_f() { |
143 |
egrep -v "$EXCLUDES" |
144 |
} |
145 |
|
146 |
meta2deps() { |
147 |
DPDEPS= |
148 |
SRCTOPS=$SRCTOP |
149 |
OBJROOTS= |
150 |
EXCLUDES= |
151 |
while : |
152 |
do |
153 |
case "$1" in |
154 |
*=*) eval export "$1"; shift;; |
155 |
-a) MACHINE_ARCH=$2; shift 2;; |
156 |
-m) MACHINE=$2; shift 2;; |
157 |
-C) CURDIR=$2; shift 2;; |
158 |
-H) HOST_TARGET=$2; shift 2;; |
159 |
-S) add_list SRCTOPS $2; shift 2;; |
160 |
-O) add_list OBJROOTS $2; shift 2;; |
161 |
-X) add_list EXCLUDES '|' $2; shift 2;; |
162 |
-R) RELDIR=$2; shift 2;; |
163 |
-T) TARGET_SPEC=$2; shift 2;; |
164 |
*) break;; |
165 |
esac |
166 |
done |
167 |
|
168 |
_th= _o= |
169 |
case "$MACHINE" in |
170 |
host) _ht=$HOST_TARGET;; |
171 |
esac |
172 |
|
173 |
for o in $OBJROOTS |
174 |
do |
175 |
case "$MACHINE,/$o/" in |
176 |
host,*$HOST_TARGET*) ;; |
177 |
*$MACHINE*|*${TARGET_SPEC:-$MACHINE}*) ;; |
178 |
*) add_list _o $o; continue;; |
179 |
esac |
180 |
for x in $_ht $TARGET_SPEC $MACHINE |
181 |
do |
182 |
case "$o" in |
183 |
"") continue;; |
184 |
*/$x/) add_list _o ${o%$x/}; o=;; |
185 |
*/$x) add_list _o ${o%$x}; o=;; |
186 |
*$x/) add_list _o ${o%$x/}; o=;; |
187 |
*$x) add_list _o ${o%$x}; o=;; |
188 |
esac |
189 |
done |
190 |
done |
191 |
OBJROOTS="$_o" |
192 |
|
193 |
case "$OBJTOP" in |
194 |
"") |
195 |
for o in $OBJROOTS |
196 |
do |
197 |
OBJTOP=$o${TARGET_SPEC:-$MACHINE} |
198 |
break |
199 |
done |
200 |
;; |
201 |
esac |
202 |
src_re= |
203 |
obj_re= |
204 |
add_list '|' -s '/*' src_re $SRCTOPS |
205 |
add_list '|' -s '*' obj_re $OBJROOTS |
206 |
|
207 |
[ -z "$RELDIR" ] && unset DPDEPS |
208 |
tf=/tmp/m2d$$-$USER |
209 |
rm -f $tf.* |
210 |
trap 'rm -f $tf.*; trap 0' 0 |
211 |
|
212 |
> $tf.dirdep |
213 |
> $tf.qual |
214 |
> $tf.srcdep |
215 |
> $tf.srcrel |
216 |
> $tf.dpdeps |
217 |
|
218 |
seenit= |
219 |
seensrc= |
220 |
lpid= |
221 |
case "$EXCLUDES" in |
222 |
"") _excludes=cat;; |
223 |
*) _excludes=_excludes_f;; |
224 |
esac |
225 |
# handle @list files |
226 |
case "$@" in |
227 |
*@[!.]*) |
228 |
for f in "$@" |
229 |
do |
230 |
case "$f" in |
231 |
*.meta) cat $f;; |
232 |
@*) xargs cat < ${f#@};; |
233 |
*) cat $f;; |
234 |
esac |
235 |
done |
236 |
;; |
237 |
*) cat /dev/null "$@";; |
238 |
esac 2> /dev/null | |
239 |
sed -e 's,^CWD,C C,;/^[CREFLM] /!d' -e "s,',,g" | |
240 |
$_excludes | |
241 |
while read op pid path junk |
242 |
do |
243 |
: op=$op pid=$pid path=$path |
244 |
# we track cwd and ldir (of interest) per pid |
245 |
# CWD is bmake's cwd |
246 |
case "$lpid,$pid" in |
247 |
,C) CWD=$path cwd=$path ldir=$path |
248 |
if [ -z "$SB" ]; then |
249 |
SB=`echo $CWD | sed 's,/obj.*,,'` |
250 |
fi |
251 |
SRCTOP=${SRCTOP:-$SB/src} |
252 |
continue |
253 |
;; |
254 |
$pid,$pid) ;; |
255 |
*) |
256 |
case "$lpid" in |
257 |
"") ;; |
258 |
*) eval ldir_$lpid=$ldir;; |
259 |
esac |
260 |
eval ldir=\${ldir_$pid:-$CWD} cwd=\${cwd_$pid:-$CWD} |
261 |
lpid=$pid |
262 |
;; |
263 |
esac |
264 |
|
265 |
case "$op,$path" in |
266 |
W,*srcrel|*.dirdep) continue;; |
267 |
C,*) |
268 |
case "$path" in |
269 |
/*) cwd=$path;; |
270 |
*) cwd=`cd $cwd/$path 2> /dev/null && /bin/pwd`;; |
271 |
esac |
272 |
# watch out for temp dirs that no longer exist |
273 |
test -d ${cwd:-/dev/null/no/such} || cwd=$CWD |
274 |
eval cwd_$pid=$cwd |
275 |
continue |
276 |
;; |
277 |
F,*) # $path is new pid |
278 |
eval cwd_$path=$cwd ldir_$path=$ldir |
279 |
continue |
280 |
;; |
281 |
*) dir=${path%/*} |
282 |
case "$path" in |
283 |
$src_re|$obj_re) ;; |
284 |
/*/stage/*) ;; |
285 |
/*) continue;; |
286 |
*) for path in $ldir/$path $cwd/$path |
287 |
do |
288 |
test -e $path && break |
289 |
done |
290 |
dir=${path%/*} |
291 |
;; |
292 |
esac |
293 |
;; |
294 |
esac |
295 |
# avoid repeating ourselves... |
296 |
case "$DPDEPS,$seensrc," in |
297 |
,*) |
298 |
case ",$seenit," in |
299 |
*,$dir,*) continue;; |
300 |
esac |
301 |
;; |
302 |
*,$path,*) continue;; |
303 |
esac |
304 |
# canonicalize if needed |
305 |
case "/$dir/" in |
306 |
*/../*|*/./*) |
307 |
rdir=$dir |
308 |
dir=`cd $dir 2> /dev/null && /bin/pwd` |
309 |
seen="$rdir,$dir" |
310 |
;; |
311 |
*) seen=$dir;; |
312 |
esac |
313 |
case "$dir" in |
314 |
${CURDIR:-.}|"") continue;; |
315 |
$src_re) |
316 |
# avoid repeating ourselves... |
317 |
case "$DPDEPS,$seensrc," in |
318 |
,*) |
319 |
case ",$seenit," in |
320 |
*,$dir,*) continue;; |
321 |
esac |
322 |
;; |
323 |
esac |
324 |
;; |
325 |
*) |
326 |
case ",$seenit," in |
327 |
*,$dir,*) continue;; |
328 |
esac |
329 |
;; |
330 |
esac |
331 |
if [ -d $path ]; then |
332 |
case "$path" in |
333 |
*/..) ldir=${dir%/*};; |
334 |
*) ldir=$path;; |
335 |
esac |
336 |
continue |
337 |
fi |
338 |
[ -f $path ] || continue |
339 |
case "$dir" in |
340 |
$CWD) continue;; # ignore |
341 |
$src_re) |
342 |
seenit="$seenit,$seen" |
343 |
echo $dir >> $tf.srcdep |
344 |
case "$DPDEPS,$reldir,$seensrc," in |
345 |
,*) ;; |
346 |
*) seensrc="$seensrc,$path" |
347 |
echo "DPDEPS_$dir/${path##*/} += $RELDIR" >> $tf.dpdeps |
348 |
;; |
349 |
esac |
350 |
continue |
351 |
;; |
352 |
esac |
353 |
# if there is a .dirdep we cannot skip |
354 |
# just because we've seen the dir before. |
355 |
if [ -s $path.dirdep ]; then |
356 |
# this file contains: |
357 |
# '# ${RELDIR}.<machine>' |
358 |
echo $path.dirdep >> $tf.qual |
359 |
continue |
360 |
elif [ -s $dir.dirdep ]; then |
361 |
echo $dir.dirdep >> $tf.qual |
362 |
seenit="$seenit,$seen" |
363 |
continue |
364 |
fi |
365 |
seenit="$seenit,$seen" |
366 |
case "$dir" in |
367 |
$obj_re) |
368 |
echo $dir;; |
369 |
esac |
370 |
done > $tf.dirdep |
371 |
_nl=echo |
372 |
for f in $tf.dirdep $tf.qual $tf.srcdep |
373 |
do |
374 |
[ -s $f ] || continue |
375 |
case $f in |
376 |
*qual) # a list of .dirdep files |
377 |
# we can prefix everything with $OBJTOP to |
378 |
# tell gendirdeps.mk that these are |
379 |
# DIRDEP entries, since they are already |
380 |
# qualified with .<machine> as needed. |
381 |
# We strip .$MACHINE though |
382 |
xargs cat < $f | sort -u | |
383 |
sed "s,^# ,,;s,^,$OBJTOP/,;s,\.${TARGET_SPEC:-$MACHINE}\$,,;s,\.$MACHINE\$,," |
384 |
;; |
385 |
*) sort -u $f;; |
386 |
esac |
387 |
_nl=: |
388 |
done |
389 |
if [ -s $tf.dpdeps ]; then |
390 |
case "$DPDEPS" in |
391 |
*/*) ;; |
392 |
*) echo > $DPDEPS;; # the echo is needed! |
393 |
esac |
394 |
sort -u $tf.dpdeps | |
395 |
sed "s,${SRCTOP}/,,;s,${SB_BACKING_SB:-$SB}/src/,," >> $DPDEPS |
396 |
fi |
397 |
# ensure we produce _something_ else egrep -v gets upset |
398 |
$_nl |
399 |
} |
400 |
|
401 |
case /$0 in |
402 |
*/meta2dep*) meta2deps "$@";; |
403 |
*/meta2dirs*) meta2dirs "$@";; |
404 |
*/meta2src*) meta2src "$@";; |
405 |
esac |