etcupdate: Add a -N flag to perform a NO_ROOT build

This is in preparation for including an etcupdate tree when performing a
-DNO_ROOT release image build. Although -DNO_ROOT can be passed via -M,
to be useful we need to mangle the resulting METALOG to mirror the
various cleanups to the tree that are done after the build (removing
generated files, empty files and empty directories), so etcupdate needs
its own flag.

Reviewed by:	jhb, pauamma
Obtained from:	CheriBSD
Differential Revision:	https://reviews.freebsd.org/D35857
This commit is contained in:
Jessica Clarke 2022-08-09 22:57:47 +01:00
parent c5e30fbdb7
commit febca0e643
2 changed files with 60 additions and 12 deletions

View file

@ -33,7 +33,7 @@
.Nd "manage updates to system files not updated by installworld"
.Sh SYNOPSIS
.Nm
.Op Fl npBF
.Op Fl npBFN
.Op Fl d Ar workdir
.Op Fl r | Fl s Ar source | Fl t Ar tarball
.Op Fl A Ar patterns
@ -44,7 +44,7 @@
.Op Fl m Ar make
.Nm
.Cm build
.Op Fl B
.Op Fl BN
.Op Fl d Ar workdir
.Op Fl s Ar source
.Op Fl L Ar logfile
@ -59,7 +59,7 @@
.Op Fl L Ar logfile
.Nm
.Cm extract
.Op Fl B
.Op Fl BN
.Op Fl d Ar workdir
.Op Fl s Ar source | Fl t Ar tarball
.Op Fl D Ar destdir
@ -518,6 +518,15 @@ option is not specified,
then a temporary
.Dq current
tree will be extracted to perform the comparison.
.It Fl N
Perform a
.Dv NO_ROOT
build when building a
.Dq current
tree.
The resulting tree will include a corresponding
.Pa METALOG
file at its root.
.It Fl p
Enable
.Dq pre-world

View file

@ -62,13 +62,13 @@
usage()
{
cat <<EOF
usage: etcupdate [-npBF] [-d workdir] [-r | -s source | -t tarball]
usage: etcupdate [-npBFN] [-d workdir] [-r | -s source | -t tarball]
[-A patterns] [-D destdir] [-I patterns] [-L logfile]
[-M options] [-m make]
etcupdate build [-B] [-d workdir] [-s source] [-L logfile] [-M options]
etcupdate build [-BN] [-d workdir] [-s source] [-L logfile] [-M options]
[-m make] <tarball>
etcupdate diff [-d workdir] [-D destdir] [-I patterns] [-L logfile]
etcupdate extract [-B] [-d workdir] [-s source | -t tarball]
etcupdate extract [-BN] [-d workdir] [-s source | -t tarball]
[-D destdir] [-L logfile] [-M options] [-m make]
etcupdate resolve [-p] [-d workdir] [-D destdir] [-L logfile]
etcupdate revert [-d workdir] [-D destdir] [-L logfile] file ...
@ -184,14 +184,24 @@ always_install()
# $1 - directory to store new tree in
build_tree()
(
local destdir dir file make
local destdir dir file make autogenfiles metatmp
make="$MAKE_CMD $MAKE_OPTIONS -DNO_FILEMON"
if [ -n "$noroot" ]; then
make="$make -DNO_ROOT"
metatmp=`mktemp $WORKDIR/etcupdate-XXXXXXX`
: > $metatmp
trap "rm -f $metatmp; trap '' EXIT; return 1" INT
trap "rm -f $metatmp" EXIT
else
metatmp="/dev/null"
trap "return 1" INT
fi
log "Building tree at $1 with $make"
exec >&3 2>&1
trap 'return 1' INT
mkdir -p $1/usr/obj
destdir=`realpath $1`
@ -219,13 +229,38 @@ build_tree()
# Purge auto-generated files. Only the source files need to
# be updated after which these files are regenerated.
rm -f $1/etc/*.db $1/etc/passwd $1/var/db/services.db || return 1
autogenfiles="./etc/*.db ./etc/passwd ./var/db/services.db"
(cd $1 && printf '%s\n' $autogenfiles >> $metatmp && \
rm -f $autogenfiles) || return 1
# Remove empty files. These just clutter the output of 'diff'.
find $1 -type f -size 0 -delete || return 1
(cd $1 && find . -type f -size 0 -delete -print >> $metatmp) || \
return 1
# Trim empty directories.
find $1 -depth -type d -empty -delete || return 1
(cd $1 && find . -depth -type d -empty -delete -print >> $metatmp) || \
return 1
if [ -n "$noroot" ]; then
# Rewrite the METALOG to exclude the files (and directories)
# removed above. $metatmp contains the list of files to delete,
# and we append #METALOG# as a delimiter followed by the
# original METALOG. This lets us scan through $metatmp in awk
# building up a table of names to delete until we reach the
# delimiter, then emit all the entries of the original METALOG
# after it that aren't in that table. We also exclude ./usr/obj
# and its children explicitly for simplicity rather than
# building up that list (and in practice only ./usr/obj itself
# will be in the METALOG since nothing is installed there).
echo '#METALOG#' >> $metatmp || return 1
cat $1/METALOG >> $metatmp || return 1
awk '/^#METALOG#$/ { metalog = 1; next }
{ f=$1; gsub(/\/\/+/, "/", f) }
!metalog { rm[f] = 1; next }
!rm[f] && f !~ /^\.\/usr\/obj(\/|$)/ { print }' \
$metatmp > $1/METALOG || return 1
fi
return 0
)
@ -1738,7 +1773,8 @@ dryrun=
ignore=
nobuild=
preworld=
while getopts "d:m:nprs:t:A:BD:FI:L:M:" option; do
noroot=
while getopts "d:m:nprs:t:A:BD:FI:L:M:N" option; do
case "$option" in
d)
WORKDIR=$OPTARG
@ -1798,6 +1834,9 @@ while getopts "d:m:nprs:t:A:BD:FI:L:M:" option; do
M)
MAKE_OPTIONS="$OPTARG"
;;
N)
noroot=YES
;;
*)
echo
usage