source: extras/farce@ e65a92f

experimental
Last change on this file since e65a92f was dc526ea, checked in by Manuel Canales Esparcia <manuel@…>, 19 years ago

Added original farce-002 scripts.

  • Property mode set to 100755
File size: 23.9 KB
RevLine 
[dc526ea]1#!/bin/bash
2
3# FARCE: Farce Assists Rebuild Comparison Evaluation ;)
4#
5# to answer the question "can it rebuild itself?"
6#
7# We expect four arguments - first directory path, filelist
8# containing the files in this directory which we wish to compare,
9# second directory path, filelist for second directory.
10#
11# Yes, we could just compare everything in each tree, but the
12# filelist script knows about files it can reasonably ignore,
13# and this also allows us to build a sytem, boot it and get a
14# list of files, build a full desktop environment, and only then
15# build and boot the "can it build itself" test system and get
16# _its_ filelist.
17#
18# What this script aims to do:
19# ____________________________
20#
21# First, report files not in both builds.
22#
23# Then, confirm symlinks point to same targets.
24#
25# After that, compare individual files -
26# if different, run the file name through 'expected'
27# to pick out files that are unlikely to match (logs,
28# pids, fstab [assumes '/' is a different device each time],
29# count these as 'expected'.
30#
31# For whatever is left, check the file type - ar archives
32# have their members extraced and compared (every member has
33# a timestamp), gzipped files are compared beyond their
34# timestamp, binaries, at least those using shared libs or
35# which are shared objects, are copied and subjected to
36# --strip-debug. If files match at this stage, count them as
37# 'accepted'.
38#
39# As a last step for any file that doesn't match, copy it
40# through some perl regexps to "process" it (convert any
41# date, time, kernel-version information from standard formats
42# into tokens, then see if the tokensi match.
43#
44# For details of the regexps, see the tokenize function.
45# Those files that match after this are also counted as
46# 'accepted'. Note that I don't always start from the kernel
47# version that I'm going to build, so this copes with e.g. perl
48# files that hardcode the kernel version.
49#
50# We now have files that don't match. A few of these seem to be
51# common to all builds - some (members of) c++ libraries or ar
52# archives, a few programs which perhaps use some sort of c++ code).
53# The file name # is passed to the 'failure' function - these
54# recognized filenames are labelled as 'predictable FAIL:',
55# anything else is labelled as 'unexpected FAIL:'.
56#
57# output:
58# stderr - files only in one of the builds, failure messages,
59# and totals.
60#
61# farce-results - more details, including which files were treated
62# as expected differences, files where neither copy could be read,
63# files treated as accepted, with the reason (and member for ar
64# archives). This data is typically up to 100 characters wide -
65# sometimes it's a bit more, but it doesn't wrap too badly in a
66# 100 character xterm.
67#
68# farce-extras - diffs for the files, or members, that didn't
69# match. This file is to establish new regexps for picking up
70# date/time/kernel-version formats.
71#
72# farce-identical - the names of the files which are identical
73#
74# farce-substitutions - whenever using tokenizeanddiff results in a
75# difference being accepted, for both versions diff the before and
76# after versions to show what got changed. If the file is a binary,
77# the output may still be hard to read. Note that I _know_ glibc
78# version strings pass one of the regexps looking for a kernel version
79# - since I expect you to use the same version of glibc for each
80# build, this is not a problem.
81#
82# farce-differ - the names of the files which could not be treated
83# as matching (whether or not I regard the failure as predictable)
84# for possible input to ICA processing.
85#
86# Copyright (C) 2005, 2006 Ken Moffat <ken@linuxfromscratch.org>
87#
88# All rights reserved.
89#
90# This program is free software; you can redistribute it and/or modify
91# it under the terms of the GNU General Public License as published by
92# the Free Software Foundation; either version 2 of the License, or (at
93# your option) any later version.
94#
95# This program is distributed in the hope that it will be useful, but
96# WITHOUT ANY WARRANTY; without even the implied warranty of
97# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
98# NON INFRINGEMENT. See the GNU General Public License for more
99# details.
100#
101# You should have received a copy of the GNU General Public License
102# along with this program; if not, write to the Free Software
103# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
104#
105
106VERSION="002"
107
108# variables for output files
109RESULT=farce-results
110EXTRAS=farce-extras
111IDENTICAL=farce-identical
112SUBS=farce-substitutions
113DIFFER=farce-differ
114
115# documenting the variables
116# C1, C2 temp files to hold disassembled code
117# D1, D2 temp directories for extracting member of ar archive
118# DIFF temp file for diffing the filelists
119# F1, F2 temp files for tokenizeanddiff
120# FTYPE obsolete, commented out
121# M1, M2 temp files to hold members of an ar archive
122# MEMBERS temp file to list members of ar archive
123# OP1, OP2 the original $PWD, needed when extracting members of ar
124# archives
125# P1, P2 paths to first and second build
126# S1, S2 temp files for shared objects
127
128# functions
129function dohelp() {
130 echo "`basename $0`: compare trees of files from a build"
131 echo "and lists of the files they contained"
132 echo ""
133 echo "`basename $0` [ -help | -version ] || path1 list1 path2 list2"
134}
135
136function emessage() {
137 # write a string to both stderr and $RESULT
138 echo "$@" >&2
139 echo "$@" >&5
140}
141
142function expected() {
143 # if we expect it to differ because of its name,
144 # allow it and report, return true ; else return false
145 case $1 in
146 /boot/grub/menu.lst)
147 # just in case somebody puts this into the main filesystem
148 true;;
149 /etc/aliases.db)
150 # some sort of database for postfix, not parsable
151 true;;
152 /etc/blkid.tab)
153 # includes dev name for rootfs
154 true;;
155 /etc/fstab)
156 # fstab, e.g. ' / ' will differ
157 true;;
158 /etc/group*)
159 true;;
160 /etc/hosts)
161 # with dhcp client, I add current ip address to this in a hook
162 true;;
163 /etc/ld.so.*)
164 # .conf and .cache can vary,
165 # particularly if one system has a full build when I run this
166 true;;
167 /etc/lilo.conf|/etc/yaboot.conf)
168 # bootloader control, I assume grub will all be on a separate
169 true;;
170 /etc/mtab)
171 # at a minimum, different '/'
172 true;;
173 /etc/ntp.drift)
174 true;;
175 /etc/passwd*)
176 true;;
177 /etc/shadow*)
178 true;;
179 /etc/ssh/*key|/etc/ssh/*pub)
180 # openssh keys
181 true;;
182 /misc/*)
183 # where I put buildscripts (which mostly won't change)
184 # and stamps containing name/time/space which will differ in the times
185 true;;
186 /root/*)
187 # expect .bash_history etc to differ - if we can read them
188 true;;
189 /usr/bin/lynx)
190 # part of my inital builds, I guess this uses anonymous namespaces
191 true;;
192 /usr/include/c++/*/*/bits/stdc++.h.gch/*)
193 # precompiled headers
194 true;;
195 /usr/lib*/libstdc++.a|/usr/lib*/libstdc++.so*|/usr/lib*/libsupc++.a)
196 # probably, anonymous namespaces
197 # libstdc++.a, libstdc++.so.n.n.n, libsupc++.a
198 true;;
199 /usr/share/info/dir)
200 # if one system has had extra stuff built, this will likely be bigger
201 true;;
202 /usr/share/man/whatis)
203 # if one system has had extra stuff built, this will likely be bigger
204 true;;
205 /var/lib/locate/locatedb)
206 # if one system has had extra stuff built, this will likely be bigger
207 true;;
208 /var/lib/nfs/*)
209 # allow nfs bookkeeping
210 true;;
211 /var/log/*)
212 true;;
213 /var/run/utmp)
214 true;;
215 /var/spool/fcron*)
216 true;;
217 /var/state/*)
218 # allow dhcp leases
219 true;;
220 /var/tmp/random-seed)
221 true;;
222 # following start with wildcards
223 *Image*|*.PPCBoot*|*vmlinuz*|*lfskernel*)
224 # compressed kernels, sometimes just building at a different
225 # date/time is enough to change the length of them, because the
226 # long format date and time is part of the compressed data
227 true;;
228 *pid*)
229 # pids, including e.g. /var/spool/postfix/pid/*
230 true;;
231 *)
232 # nothing else is expected to be different
233 false;;
234 esac
235 if [ $? -eq 0 ]; then
236 message "expected difference in $1"
237 let expected=$expected+1
238 case $TYPE in
239 AR)
240 let EXPAR=$EXPAR+1
241 ;;
242 ELF)
243 let EXPELF=$EXPELF+1
244 ;;
245 UNK)
246 let EXPUNK=$EXPUNK+1
247 ;;
248 # so far, no other valid types, so don't accumulate them
249 *)
250 emessage "internal error, expected difference for $1 of type $TYPE not allowed"
251 exit 2
252 ;;
253 esac
254 true
255 else
256 false
257 fi
258}
259
260function failure() {
261 # first parm is filename or token
262 # second parm is the error message
263 # update the appropriate total
264 # and write to both stderr and the results
265 # by using emessage
266
267 let different=$different+1
268 case $TYPE in
269 AR)
270 let DIFAR=$DIFAR+1
271 ;;
272 ELF)
273 let DIFELF=$DIFELF+1
274 ;;
275 GZ)
276 let DIFGZ=$DIFGZ+1
277 ;;
278 SYM)
279 let DIFSYM=$DIFSYM+1
280 ;;
281 UNK)
282 let DIFUNK=$DIFUNK+1
283 ;;
284 *)
285 emessage "internal error in failure() for TYPE $TYPE"
286 exit 2
287 ;;
288 esac
289 test -f ${P1}$1 && echo $1 >&9
290 emessage "FAIL: $2"
291}
292
293function fatal() {
294 # unrecoverable error
295 echo $*
296 exit 1
297}
298
299function filetype() {
300 TYPE=`file ${P1}${FILE}`
301 case $TYPE in
302 *'current ar archive'*)
303 let TOTAR=$TOTAR+1
304 TYPE=AR
305 ;;
306 *' ELF '*)
307 let TOTELF=$TOTELF+1
308 TYPE=ELF
309 ;;
310 *'gzip compressed data'*)
311 let TOTGZ=$TOTGZ+1
312 TYPE=GZ
313 ;;
314 *)
315 let TOTUNK=$TOTUNK+1
316 TYPE=UNK
317 ;;
318 esac
319}
320
321function message() {
322 # write a string to $RESULT
323 echo $* >&5
324}
325
326function onlyone() {
327 #report files only in one build
328 # text should go to both stderr and the results,
329 # but blank lines only go to the results
330 if [ $1 == '<' ]; then
331 emessage "File(s) only in the first build"
332 else
333 emessage "File(s) only in the second build"
334 fi
335 message ""
336 FILES=`cat $DIFF | grep "^$1" | cut -d ' ' -f 2`
337 for F in $FILES; do
338 emessage $F
339 let only=$only+1
340 done
341 message ""
342}
343
344# 'test' functions are called with three arguments:
345# the two pathes and the filename
346# - we know the file is of this type, so see if we
347# can get it to match by reasonalbe means.
348# if not, treat it as different.
349#
350# NB if pathes are absolute, we need to prefix them
351# with the original $PWD to access the .a files
352#
353function testar() {
354 # ar archives include timestamps for the members,
355 # but diff doesn't show file timestamps unless the data differs
356 # put out a message to help locate which archive any messages
357 # about the members refer to.
358
359 # try just stripping them U1,2 undebuggable
360 U1=`mktemp` || fatal "cannot create a temporary file"
361 U2=`mktemp` || fatal "cannot create a temporary file"
362 cp ${1}${3} $U1
363 cp ${2}${3} $U2
364 strip --strip-debug $U1
365 strip --strip-debug $U2
366 cmp -s $U1 $U2
367 rm $U1 $U2
368 if [ $? -eq 0 ]; then
369 let accepted=$accepted+1
370 let ACCAR=$ACCAR+1
371 message "archive $3 matches after strip --strip-debug"
372 return
373 fi
374 # rest of this function retained primarily for pathologically bad builds
375 # put out a message in the log to help identify which archive has issues.
376 message "examining ar archive $3"
377 D1=`mktemp -d` || fatal "cannot create a temporary directory"
378 D2=`mktemp -d` || fatal "cannot create a temporary directory"
379 cd $D1
380 ar -x ${OP1}${1}${3}
381 cd $D2
382 ar -x ${OP2}${2}${3}
383 cd
384 # diff the members - true means they match
385 diff -Na $D1 $D2 >/dev/null
386 if [ $? -eq 0 ]; then
387 message "accept: $3 after diffing the members"
388 let accepted=$accepted+1
389 let ACCAR=$ACCAR+1
390 else
391 # process individual members to eliminate date/time/kernel-version
392 # first, check the members are the same
393 M1=`mktemp` || fatal "cannot create a temporary file"
394 M2=`mktemp` || fatal "cannot create a temporary file"
395 cd $D1
396 MEMBERS=
397 for F in *; do
398 MEMBERS="$MEMBERS $F"
399 done
400 cd
401 echo $MEMBERS | sort >$M1
402 cd $D2
403 MEMBERS=
404 for F in *; do
405 MEMBERS="$MEMBERS $F"
406 done
407 cd
408 echo $MEMBERS | sort >$M2
409 cmp -s $M1 $M2
410 if [ $? -ne 0 ]; then
411 # oh dear, different members
412 echo "list of members differs for archive $3" >&6
413 diff $M1 $M2 >&6
414 failure $3 "$3 list of members differs"
415 else
416 # members (names) are same,
417 # process each one
418 STATUS=0
419 for M in $MEMBERS; do
420 #avoid firing up perl on matching members
421 cmp -s $D1/$M $D2/$M
422 if [ $? -ne 0 ]; then
423 tokenizeanddiff $D1/$M $D2/$M $FILE:$M
424 if [ $? -eq 0 ]; then
425 message "member $M matches after processing"
426 else
427 message "member $M DIFFERS after processing"
428 STATUS=1
429 fi
430 fi
431 done
432 if [ $STATUS -eq 0 ]; then
433 let accepted=$accepted+1
434 let ACCAR=$ACCAR+1
435 else
436 let different=$different+1
437 let DIFAR=$DIFAR+1
438 echo $3 >&9
439 emessage "FAIL: in $3"
440 fi
441 fi
442 rm $M1 $M2
443 fi
444 rm -rf $D1 $D2
445}
446
447function testgzip() {
448 # bytes 4,5,6,7 are the timestamp, so ignore these
449 cmp -s -i 8 ${1}${3} ${2}${3}
450 if [ $? -eq 0 ]; then
451 message "accept: $3 after ignoring gzip timestamp"
452 let accepted=$accepted+1
453 let ACCGZ=$ACCGZ+1
454 else
455 failure $3 " $3 even after ignoring gzip timestamp"
456 fi
457}
458
459function testso() {
460 # shared object - first try stripping it
461 # in fact, this now handles ALL ELF files
462 S1=`mktemp` || fatal "cannot create a temporary file"
463 S2=`mktemp` || fatal "cannot create a temporary file"
464 cp ${1}${3} $S1
465 strip --strip-debug $S1
466 cp ${2}${3} $S2
467 strip --strip-debug $S2
468 cmp -s $S1 $S2
469 if [ $? -eq 0 ]; then
470 message "accept: $3 after --strip-debug"
471 let accepted=$accepted+1
472 let ACCELF=$ACCELF+1
473 else
474 tokenizeanddiff $S1 $S2 $3
475 if [ $? -ne 0 ]; then
476 failure $3 " $3 differs after stripping and processing"
477 else
478 message "accept: $3 after --strip-debug and processing"
479 let accepted=$accepted+1
480 let ACCELF=$ACCELF+1
481 fi
482 fi
483 rm $S1 $S2
484}
485
486function tokenize() {
487 # use regexes to replace date/time/kernel-version text
488 # with tokens which may allow files to match even though
489 # they have hardcoded date/time/kernel-version.
490 # arguments are file to process, and where to put it.
491 # these regexes are somewhat long, and the order they
492 # are applied in is important (to stop short ones being
493 # used when a longer version would match).
494 # KV00 linux version date (e.g. as in the kernel itself)
495 # allow 2 or 3 groups of three alphas here - optional smp, with day, mon
496 # KV01 kernel version, including possible cpu details (that is for cdda2wav)
497 # KV02 just the version, in quotes e.g. "2.6.12.6" or '2.6.13', for perl stuff
498 # except that "|' gives me grif, so try a boundary
499 # also, it might need local version on the end, I really want
500 # quote2.\d+.\d+.{0,32}quote - it is the quotes that don't work.
501 # DT00 Day Mon .d+ hh:mm:ss TZN CCYY variations include non-caps and 'mon d'
502 # DT01 Mon .d+ CCYY hh:mm:ss
503 # DT02 hh:mm:ss Mon .d CCYY
504 # DT03 Mon .d CCYY
505 # DT04 Day Mon { ,d}d hh:mm:ss CCYY - for groff example postscript files
506 # (somewhat similar to DT00, but ' d' or ' dd' for day of month and no TZN )
507 # DT05 hh:mm:ss
508 # DT06 ISO date using space as separator
509 # DT07 ISO date using dash as separator
510 # DT08 ISO date using slash as separator
511 # DT09 fullmonth (capitalised), day number, comma, 4-digit year (groff 1.18.1 ps)
512 # DT10 dd, fullmonth (capitalised), 4-digit year (groff 1.18.1 manpages)
513 # DT11 '(xample comma space digit(s) backslash ) in groff memef.ps which is
514 # quite clearly the day of the month when it was compiled, preceded by 'example'
515 # with something weird between the e and the x.
516
517 if [ $# -ne 2 ]; then
518 fatal "tokenizing called with $# arguments : $*"
519 fi
520
521 cat $1 | perl -p \
522 -e 's/(L|l)inux.*\d\.\d\.\d+.* \#\d+( [A-Za-z][a-z]{2}){2,3} \d+ \d\d:\d\d:\d\d [A-Za-z]{3} \d{4}\b/%KV00%/g;' \
523 -e 's/(L|l)inux( (\w|_)+)?(-| |_)\d\.\d(\.\d+){1,2}((-|_)?(\w|_)+)?( |\000)*/%KV01%/g;' \
524 -e 's/\W2(\.\d+){2,3}(-|_)?((\w|_)+)?\s*\W/%KV02%/g;' \
525 -e 's/\b([A-Za-z][a-z]{2} ){2}( |\d)?\d \d\d:\d\d:\d\d [A-Za-z]{3} \d{4}\b/%DT00%/g;' \
526 -e 's/\b[A-Z][a-z]{2} ( |\d)\d \d{4} \d\d:\d\d:\d\d\b/%DT01%/g;' \
527 -e 's/\b\d\d:\d\d:\d\d [A-Z][a-z]{2} ( |\d)\d \d{4}\b/%DT02%/g;' \
528 -e 's/\b[A-Z][a-z]{2} ( |\d)\d \d{4}\b/%DT03%/g;' \
529 -e 's/\b([A-Z][a-z]{2} ){2}( |\d)\d \d\d:\d\d:\d\d \d{4}/%DT04%/g;' \
530 -e 's/\b\d\d:\d\d:\d\d\b/%DT05%/g;' \
531 -e 's/\b\d{4} \d\d \d\d\b/%DT06%/g;' \
532 -e 's/\b\d{4}-\d\d-\d\d\b/%DT07%/g;' \
533 -e 's/\b\d{4}\/\d\d\/\d\d\b/%DT08%/g;' \
534 -e 's/\b[A-Z][a-z]{2,} \d{1,2}, \d{4}/%DT09%/g;' \
535 -e 's/\b\d\d [A-Z][a-z]{2,} \d{4}/%DT10%/g;' \
536 -e 's/\(xample, \d{1,2}\\\)/%DT11%/g;' \
537 >$2
538}
539
540function tokenizeanddiff() {
541 # Call tokenize for the inputs, then compare the results
542 # Input arguments are path/filename for old and new versions
543 # third parm is readable name (filename, or archivename:member)
544 # to help understand what is in the extras output.
545 # - sometimes called for files, but other times called for
546 # members of ar archives extracted into temporary directories
547 #message tokenizeanddiff called for $1 $2 $3
548 F1=`mktemp` || fatal "cannot create a temporary file"
549 F2=`mktemp` || fatal "cannot create a temporary file"
550 tokenize $1 $F1
551 tokenize $2 $F2
552
553 # actually, cmp is probably more efficient
554 # but for picking up the pieces it will be better to
555 # use diff to see what got through.
556 cmp -s $F1 $F2
557 TOKENRESULT=$?
558 if [ $TOKENRESULT -ne 0 ]; then
559 echo "failure in $3..." >&6
560 diff -a $F1 $F2 >&6
561 rm $F1 $F2
562 false
563 else
564 # show what we did
565 echo "substitutions for $3" >&8
566 echo "build one" >&8
567 diff -a $1 $F1 >&8
568 echo "build two" >&8
569 diff -a $2 $F2 >&8
570 rm $F1 $F2
571 true
572 fi
573}
574
575function validateargs() {
576# validate the arguments
577BAD=0
578if ! [ -d $1 ]; then
579 echo "Error: first argument is not a directory" >&2
580 let BAD=$BAD+1
581fi
582NAME=`basename ${2%%-*}`
583if [ $NAME != filelist ]; then
584 echo "Error: second argument is not a recognized filelist" >&2
585 let BAD=$BAD+1
586fi
587if ! [ -d $3 ]; then
588 echo "Error: third argument is not a directory" >&2
589 let BAD=$BAD+1
590fi
591NAME=`basename ${4%%-*}`
592if [ $NAME != filelist ]; then
593 echo "Error: fourth argument is not a recognized filelist" >&2
594 let BAD=$BAD+1
595fi
596for I in $1 $2 $3 $4; do
597 if ! [ -r $I ]; then
598 echo "Error: cannot read $I" >&2
599 let BAD=$BAD+1
600 fi
601done
602if [ $1 == $3 ]; then
603 echo "Error: directory pathes are identical" >&2
604 let BAD=$BAD+1
605fi
606if [ $2 == $4 ]; then
607 echo "Error: filelist names are identical" >&2
608 let BAD=$BAD+1
609fi
610if [ $BAD -eq 0 ]; then
611 ARGS=valid
612fi
613}
614
615# Mainline
616ARGS=unproven
617OUTDIR=
618if [ $# -eq 1 ]; then
619 case $1 in
620 -version|--version)
621 echo "`basename $0` version $VERSION"
622 exit 0
623 ;;
624 -help|--help)
625 dohelp
626 exit 0
627 ;;
628 esac
629fi
630if [ $1 = "--directory" ]; then
631 OUTDIR=$2
632 shift 2
633 grep '/$' $OUTDIR >/dev/null 2>&1 || OUTDIR=`echo $OUTDIR | sed 's%$%/%'`
634 echo "creating directory $OUTDIR"
635 mkdir -p $OUTDIR
636 if [ $? -ne 0 ]; then
637 echo "cannot mkdir $OUTDIR"
638 exit 1
639 fi
640fi
641if [ $# -eq 4 ]; then
642 validateargs $*
643fi
644if ! [ $ARGS == valid ]; then
645 dohelp
646 fatal "`basename $0`: error in arguments"
647fi
648
649# ok, we're happy, lets hit these files
650exec 5>${OUTDIR}$RESULT
651exec 6>${OUTDIR}$EXTRAS
652exec 7>${OUTDIR}$IDENTICAL
653exec 8>${OUTDIR}$SUBS
654exec 9>${OUTDIR}$DIFFER
655
656>${OUTDIR}$RESULT
657if [ $? -ne 0 ]; then
658 fatal "cannot write to ${OUTDIR}$RESULT"
659fi
660
661emessage "will compare:"
662emessage " first build at $1 with files listed in $2"
663emessage "second build at $3 with files listed in $4"
664
665let accepted=0
666let different=0
667let expected=0
668let matched=0
669let only=0
670let predictable=0
671let unreadable=0
672let total=0
673
674# break down the accepted
675let ACCAR=0
676let ACCELF=0
677let ACCGZ=0
678let ACCUNK=0
679
680# break down definitely different
681let DIFAR=0
682let DIFELF=0
683let DIFGZ=0
684let DIFSYM=0
685let DIFUNK=0
686
687# break down the expected differences
688let EXPAR=0
689let EXPELF=0
690let EXPGZ=0
691let EXPUNK=0
692
693# break down the identical files
694let MATAR=0
695let MATELF=0
696let MATGZ=0
697let MATSYM=0
698let MATUNK=0
699
700# break down how many of each type
701let TOTAR=0
702let TOTELF=0
703let TOTGZ=0
704let TOTSYM=0
705let TOTUNK=0
706
707# now identify differences between the two trees
708DIFF=`mktemp` || fatal "cannot create a temporary file"
709diff $2 $4 >$DIFF
710
711for RUN in '<' '>' ; do
712 grep -q "$RUN" $DIFF && onlyone "$RUN"
713done
714
715rm $DIFF
716
717# and compare them
718message "Results of file comparison:"
719message ""
720
721# Strip any trailing slash from the path for tidyness,
722# because the filenames all start with a slash. Unfortunately,
723# unfortunately, '/' becomes empty, which breaks subroutines,
724# so special case it.
725# also, to process ar archives we need to extract them in temp
726# directories - that means that after cd'ing we've broken any
727# relative path, so save original pwd as necessary.
728P1=`echo $1 | sed 's%/$%%'`
729echo $1 | grep '^/' >/dev/null
730if [ $? -ne 0 ]; then
731 # relative path
732 OP1=${PWD}/
733 #echo "setting OP1 to $OP1"
734else
735 OP1=
736 #echo "$1 is an absolute path"
737fi
738test -z "$P1" && P1='/'
739P2=`echo $3 | sed 's%/$%%'`
740echo $3 | grep '^/' >/dev/null
741if [ $? -ne 0 ]; then
742 # relative path
743 OP2=${PWD}/
744 #echo "setting OP2 to $OP2"
745else
746 OP2=
747 #echo "$3 is an absolute path"
748fi
749test -z "$P2" && P2='/'
750
751echo "about to read $2"
752while read FILE ; do
753#echo "process $FILE"
754#echo "test existence of ${P2}${FILE}"
755 # confirm it exists in second build
756 # we have already reported files only in one build
757 if [ -f ${P2}"${FILE}" ]; then
758 let total=$total+1
759 # check we can read both of them
760 # or count as unreadable - I used to separate only-one-unreadable,
761 # but if you compre '/' and a _copy_ of /mnt/lfs that assumption
762 # breaks, so be less picky.
763 if ! [ -r "${P1}${FILE}" ] || ! [ -r "${P2}${FILE}" ]; then
764 message "cannot read one or both versions of $FILE"
765 let unreadable=$unreadable+1
766 continue
767 fi
768 if [ -h "${P1}${FILE}" ]; then
769 # for symlink, look at what it points to
770 # exceptionally, do not call filetype
771 TYPE=SYM
772 let TOTSYM=$TOTSYM+1
773 SL1=`ls -l "${P1}${FILE}" | awk '{ print $11 }'`
774 SL2=`ls -l "${P2}${FILE}" | awk '{ print $11 }'`
775 if [ "$SL1" = "$SL2" ]; then
776 echo "symlink $FILE matches for $SL1" >&5
777 let matched=$matched+1
778 let MATSYM=$MATSYM+1
779 else
780 failure TARGET " symlink $FILE points to $SL1 and $SL2"
781 echo $FILE >&9
782 fi
783 else
784 # regular file, start by typing it for accounting,
785 # then compare it
786 filetype ${P1}${FILE}
787 cmp -s "${P1}${FILE}" "${P2}${FILE}"
788 if [ $? -eq 0 ]; then
789 let matched=$matched+1
790 case $TYPE in
791 AR)
792 let MATAR=$MATAR+1
793 ;;
794 ELF)
795 let MATELF=$MATELF+1
796 ;;
797 GZ)
798 let MATGZ=$MATGZ+1
799 ;;
800 UNK)
801 let MATUNK=$MATUNK+1
802 ;;
803 *)
804 echo "unexpected TYPE of $TYPE for $FILE" >&2
805 exit 2
806 ;;
807 esac
808 echo ${FILE} >&7
809 else
810 # seems different, can we do better ?
811 # test if we expect it to differ
812 expected $FILE
813 if [ $? -ne 0 ]; then
814 case $TYPE in
815 GZ)
816 testgzip $P1 $P2 $FILE ;;
817 AR)
818 testar $P1 $P2 $FILE ;;
819 ELF)
820 testso $P1 $P2 $FILE ;;
821 *)
822 # long-stop - strip dates from text files
823 tokenizeanddiff "${P1}${FILE}" "${P2}${FILE}" "$FILE"
824 if [ $? -eq 0 ]; then
825 message "accepted $FILE after processing"
826 let accepted=$accepted+1
827 let ACCUNK=$ACCUNK+1
828 else
829 failure "$FILE" " $FILE is different"
830 fi
831 ;;
832 esac
833 fi
834 fi
835 fi
836 fi
837done < $2
838
839message ""
840# write totals to stderr as well as the results file
841emessage "$only files in only one of the builds"
842emessage "$total files compared, of which"
843emessage "$unreadable files could not be read, skipped"
844emessage "$matched files are identical"
845emessage "$expected files differed as expected"
846emessage "$accepted files had allowable differences"
847#emessage "$predictable files differed as they normally do"
848emessage "$different files differed"
849
850# totals of different file types
851emessage ""
852emessage "$TOTAR ar archives"
853emessage " of which $MATAR are identical"
854emessage " of which $ACCAR are accepted after strip-debug or extracting, diffing, tokenizing"
855emessage " of which $EXPAR differed as expected"
856emessage " of which $DIFAR differed"
857emessage "$TOTELF ELF executables or shared libraries"
858emessage " of which $MATELF are identical"
859emessage " of which $ACCELF are accepted after stripping and tokenizing"
860emessage " of which $EXPELF differed as expected"
861emessage " of which $DIFELF differed"
862emessage "$TOTGZ gzipped files"
863emessage " of which $MATGZ are identical"
864emessage " of which $ACCGZ are accepted after comparing beyond timestamp"
865emessage " of which $DIFGZ are different"
866emessage "$TOTSYM symbolic links"
867emessage " of which $MATSYM are identical"
868emessage " of which $DIFSYM have different targets"
869emessage "$TOTUNK other files"
870emessage " of which $MATUNK are identical"
871emessage " of which $ACCUNK are accepted after tokenizing"
872emessage " of which $EXPUNK differed as expected"
873emessage " of which $DIFUNK differed"
874
Note: See TracBrowser for help on using the repository browser.