1#! /bin/sh --
2#
3#         $NetBSD: checkflist,v 1.46 2022/08/21 07:10:03 lukem Exp $
4#
5# Verify output of makeflist against contents of ${DESTDIR} and ${metalog}.
6
7if [ -z "${DESTDIR}" ]; then
8          echo "DESTDIR must be set"
9          exit 1
10fi
11
12prog="${0##*/}"
13rundir="$(dirname "$0")" # ${0%/*} isn't good enough when there's no "/"
14. "${rundir}/sets.subr"
15
16#
17# * ${SETS_DLIST}: files present in DESTDIR.
18# * ${SETS_FLIST}: files mentioned in flist;
19# * ${SETS_MLIST}: files mentioned in metalog;
20#
21SETS_DLIST="${DESTDIR}/SETS.dlist"
22SETS_FLIST="${DESTDIR}/SETS.flist"
23SETS_MLIST="${DESTDIR}/SETS.mlist"
24
25#
26# * ${SETS_METALOG_EXTRA}: Files in METALOG but missing from DESTDIR."
27# * ${SETS_METALOG_MISSING}: Files in DESTDIR but missing from METALOG."
28# * ${SETS_DESTDIR_EXTRA}: Files in DESTDIR but missing from setlist."
29# * ${SETS_DESTDIR_MISSING}: Files in setlist but missing from DESTDIR."
30#
31SETS_METALOG_EXTRA="${DESTDIR}/SETS.metalog.extra"
32SETS_METALOG_MISSING="${DESTDIR}/SETS.metalog.missing"
33SETS_DESTDIR_EXTRA="${DESTDIR}/SETS.destdir.extra"
34SETS_DESTDIR_MISSING="${DESTDIR}/SETS.destdir.missing"
35
36es=0
37cleanup()
38{
39          if [ ${es} -gt 255 ]; then
40                    es=255
41          fi
42          exit ${es}
43}
44trap cleanup 0 2 3 13                   # EXIT INT QUIT PIPE
45
46origin=.
47xargs=""
48dargs=""
49metalog=
50allowextra=false
51allowmissing=false
52
53# handle args
54while getopts xbL:M:em ch; do
55          case ${ch} in
56          x)
57                    xargs="-x"
58                    origin="./etc/X11 ./etc/fonts ./usr/X11R7"
59                    ;;
60          # backward compat
61          b)
62                    xargs="-b"
63                    ;;
64          L)
65                    xargs="-L ${OPTARG}"
66                    ;;
67          M)
68                    metalog="${OPTARG}"
69                    ;;
70          e)
71                    allowextra=true
72                    ;;
73          m)
74                    allowmissing=true
75                    ;;
76          *)
77                    cat 1>&2 <<USAGE
78Usage: ${prog} [-x|-b|-L lists] [-M metalog] [-e] [-m]
79          -x                  check only x11 lists
80          -b                  check netbsd + x11 lists
81          -L base,x,ext       check specified lists
82          -M metalog          metalog file
83          -e                  extra files are not considered an error
84          -m                  missing files are not considered an error
85USAGE
86                    exit 1
87                    ;;
88          esac
89done
90shift $((${OPTIND} - 1))
91
92#
93# Exceptions to flist checking (all begin with "./"):
94#
95# * ignore var/db/syspkg and its contents
96# * ignore METALOG and METALOG.*
97# * ignore etc/mtree/set.*
98#
99ignore_exceptions()
100{
101IGNORE_REGEXP_SYSPKG="^\./var/db/syspkg(\$|/)"
102IGNORE_REGEXP_METALOG="^\./METALOG(\..*)?\$"
103IGNORE_REGEXP_SETS="^\./SETS\..*\$"
104IGNORE_REGEXP_MTREE="^\./etc/mtree/set\.[a-z]*\$"
105
106          ${EGREP} -v \
107                    -e "${IGNORE_REGEXP_SYSPKG}" \
108                    -e "${IGNORE_REGEXP_METALOG}" \
109                    -e "${IGNORE_REGEXP_SETS}" \
110                    -e "${IGNORE_REGEXP_MTREE}"
111}
112
113#
114# Here would be a good place to add custom exceptions to flist checking.
115#
116
117#
118# Make three lists:
119#
120# All three lists are filtered against ${IGNORE_REGEXP}.
121#
122
123generate_dlist()
124{
125( cd "${DESTDIR}" && ${FIND} ${origin} \
126          \( -type d -o -type f -o -type l \) -print ) \
127          | ${SORT} -u | ignore_exceptions >"${SETS_DLIST}"
128}
129
130generate_flist()
131{
132${HOST_SH} "${rundir}/makeflist" ${xargs} ${dargs} \
133          | ${SORT} -u | ignore_exceptions >"${SETS_FLIST}"
134}
135
136generate_mlist()
137{
138if [ -n "${metalog}" ]; then
139          ${AWK} '{print $1}' <"${metalog}" \
140          | ${SORT} -u | ignore_exceptions >"${SETS_MLIST}"
141else
142          SETS_MLIST=/dev/null
143fi
144}
145
146generate_mlist_missing()
147{
148          ${COMM} -23 "${SETS_DLIST}" "${SETS_MLIST}" > "${SETS_METALOG_MISSING}"
149}
150
151generate_mlist_extra()
152{
153          ${COMM} -13 "${SETS_DLIST}" "${SETS_MLIST}" > "${SETS_METALOG_EXTRA}"
154}
155
156generate_dlist_missing()
157{
158          ${COMM} -23 "${SETS_FLIST}" "${SETS_DLIST}" > "${SETS_DESTDIR_MISSING}"
159}
160
161generate_dlist_extra()
162{
163          ${COMM} -13 "${SETS_FLIST}" "${SETS_DLIST}" > "${SETS_DESTDIR_EXTRA}"
164}
165
166exist_case_insensitive()
167{
168          while read f; do
169                    [ -f "${DESTDIR}/${f}" ] || \
170                    [ -d "${DESTDIR}/${f}" ] || \
171                    [ -L "${DESTDIR}/${f}" ] || \
172                    echo "$f"
173          done
174}
175
176#
177# compare DESTDIR with METALOG, and report on differences.
178#
179compare_metalog()
180{
181    # Handle case insensitive filesystems
182    mv -f "${SETS_METALOG_EXTRA}" "${SETS_METALOG_EXTRA}.all"
183    exist_case_insensitive < "${SETS_METALOG_EXTRA}.all" > "${SETS_METALOG_EXTRA}"
184    rm -f "${SETS_METALOG_EXTRA}.all"
185
186    check_metalog_extra
187    check_metalog_missing
188}
189
190check_metalog_extra()
191{
192    if [ -s "${SETS_METALOG_EXTRA}" ]; then
193          count="$(${AWK} 'END {print NR}' "${SETS_METALOG_EXTRA}")"
194          echo ""
195          echo "=======  ${count} extra files in METALOG  ========="
196          echo "Files in METALOG but missing from DESTDIR."
197          echo "File was deleted after installation ?"
198          echo "------------------------------------------"
199          cat "${SETS_METALOG_EXTRA}"
200          echo "=========  end of ${count} extra files  ==========="
201          echo ""
202          es=1 # this is fatal even if ${allowextra} is true
203    fi
204}
205
206check_metalog_missing()
207{
208    if [ -s "${SETS_METALOG_MISSING}" ]; then
209          count="$(${AWK} 'END {print NR}' "${SETS_METALOG_MISSING}")"
210          echo ""
211          echo "======  ${count} missing files in METALOG  ========"
212          echo "Files in DESTDIR but missing from METALOG."
213          echo "File installed but not registered in METALOG ?"
214          echo "------------------------------------------"
215          cat "${SETS_METALOG_MISSING}"
216          echo "========  end of ${count} missing files  =========="
217          echo ""
218          es=1 # this is fatal even if ${allowmissing} is true
219    fi
220}
221
222#
223# compare flist with DESTDIR, and report on differences.
224#
225compare_destdir()
226{
227# Handle case insensitive filesystems
228mv -f "${SETS_DESTDIR_MISSING}" "${SETS_DESTDIR_MISSING}.all"
229exist_case_insensitive < "${SETS_DESTDIR_MISSING}.all" > "${SETS_DESTDIR_MISSING}"
230rm -f "${SETS_DESTDIR_MISSING}.all"
231
232check_destdir_extra
233check_destdir_missing
234}
235
236check_destdir_extra()
237{
238if [ -s "${SETS_DESTDIR_EXTRA}" ]; then
239          count="$(${AWK} 'END {print NR}' "${SETS_DESTDIR_EXTRA}")"
240          echo ""
241          echo "=======  ${count} extra files in DESTDIR  ========="
242          echo "Files in DESTDIR but missing from flist."
243          echo "File is obsolete or flist is out of date ?"
244          if ${allowextra}; then
245                    echo "This is non-fatal, due to '-e' option."
246          else
247                    es=1
248          fi
249          echo "------------------------------------------"
250          cat "${SETS_DESTDIR_EXTRA}"
251          echo "=========  end of ${count} extra files  ==========="
252          echo ""
253fi
254}
255
256check_destdir_missing()
257{
258if [ -s "${SETS_DESTDIR_MISSING}" ]; then
259          count="$(${AWK} 'END {print NR}' "${SETS_DESTDIR_MISSING}")"
260          echo ""
261          echo "======  ${count} missing files in DESTDIR  ========"
262          echo "Files in flist but missing from DESTDIR."
263          echo "File wasn't installed ?"
264          if ${allowmissing}; then
265                    echo "This is non-fatal, due to '-m' option."
266          else
267                    es=1
268          fi
269          echo "------------------------------------------"
270          cat "${SETS_DESTDIR_MISSING}"
271          echo "========  end of ${count} missing files  =========="
272          echo ""
273fi
274}
275
276generate_dlist
277generate_flist
278generate_mlist
279
280generate_mlist_missing
281generate_mlist_extra
282
283generate_dlist_missing
284generate_dlist_extra
285
286if false && [ -n "${metalog}" ]; then
287          # XXX: Temporarily disabled due to problems with obsolete files in metalog
288          compare_metalog
289else
290          compare_destdir
291fi
292
293exit 0              # cleanup will exit with ${es}
294