svn commit: r260650 - in stable/9: tools/regression/usr.sbin/etcupdate usr.sbin usr.sbin/etcupdate

John Baldwin jhb at FreeBSD.org
Tue Jan 14 21:20:53 UTC 2014


Author: jhb
Date: Tue Jan 14 21:20:51 2014
New Revision: 260650
URL: http://svnweb.freebsd.org/changeset/base/260650

Log:
  MFC 238423,238426,238428,258063,258063,258066,258097,258185,259134:
  The etcupdate utility is a tool for managing updates to files that are
  not updated as part of `make installworld' such as files in /etc.  It
  manages updates by doing a three-way merge of changes made to these files
  against the local versions.  It is also designed to minimize the amount
  of user intervention with the goal of simplifying upgrades for clusters
  of machines.

Added:
     - copied from r238423, head/tools/regression/usr.sbin/etcupdate/
  stable/9/tools/regression/usr.sbin/etcupdate/preworld.sh
     - copied, changed from r258066, head/tools/regression/usr.sbin/etcupdate/preworld.sh
  stable/9/tools/regression/usr.sbin/etcupdate/tzsetup.sh
     - copied unchanged from r259134, head/tools/regression/usr.sbin/etcupdate/tzsetup.sh
     - copied from r238423, head/usr.sbin/etcupdate/
Directory Properties:
  stable/9/tools/regression/usr.sbin/etcupdate/   (props changed)
  stable/9/usr.sbin/etcupdate/   (props changed)
Modified:
  stable/9/tools/regression/usr.sbin/etcupdate/always.sh
  stable/9/tools/regression/usr.sbin/etcupdate/conflicts.sh
  stable/9/tools/regression/usr.sbin/etcupdate/fbsdid.sh
  stable/9/tools/regression/usr.sbin/etcupdate/ignore.sh
  stable/9/tools/regression/usr.sbin/etcupdate/tests.sh
  stable/9/usr.sbin/Makefile   (contents, props changed)
  stable/9/usr.sbin/etcupdate/etcupdate.8
  stable/9/usr.sbin/etcupdate/etcupdate.sh
Directory Properties:
  stable/9/tools/regression/usr.sbin/   (props changed)
  stable/9/usr.sbin/   (props changed)

Modified: stable/9/tools/regression/usr.sbin/etcupdate/always.sh
==============================================================================
--- head/tools/regression/usr.sbin/etcupdate/always.sh	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/tools/regression/usr.sbin/etcupdate/always.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -33,13 +33,17 @@ WORKDIR=work
 
 usage()
 {
-	echo "Usage: always.sh [-w workdir]"
+	echo "Usage: always.sh [-s script] [-w workdir]"
 	exit 1
 }
 
-# Allow the user to specify an alternate work directory.
-while getopts "w:" option; do
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
 	case $option in
+		s)
+			COMMAND="sh $OPTARG"
+			;;
 		w)
 			WORKDIR=$OPTARG
 			;;
@@ -372,7 +376,7 @@ fi
 
 build_trees
 
-etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
 
 cat > $WORKDIR/correct.out <<EOF
   D /dirchange/fromdir/extradir/file
@@ -492,7 +496,7 @@ fifo /dirchange/todir/difftype
 
 build_trees
 
-etcupdate -r -A '/first*' -A '/second* /*di*' -d $WORKDIR -D $TEST > \
+$COMMAND -r -A '/first*' -A '/second* /*di*' -d $WORKDIR -D $TEST > \
     $WORKDIR/test1.out
 
 cat > $WORKDIR/correct1.out <<EOF

Modified: stable/9/tools/regression/usr.sbin/etcupdate/conflicts.sh
==============================================================================
--- head/tools/regression/usr.sbin/etcupdate/conflicts.sh	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/tools/regression/usr.sbin/etcupdate/conflicts.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -33,13 +33,17 @@ WORKDIR=work
 
 usage()
 {
-	echo "Usage: tests.sh [-w workdir]"
+	echo "Usage: conflicts.sh [-s script] [-w workdir]"
 	exit 1
 }
 
-# Allow the user to specify an alternate work directory.
-while getopts "w:" option; do
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
 	case $option in
+		s)
+			COMMAND="sh $OPTARG"
+			;;
 		w)
 			WORKDIR=$OPTARG
 			;;
@@ -84,7 +88,7 @@ default:\\
         :welcome=/etc/motd:
 EOF
 
-	etcupdate -r -d $WORKDIR -D $TEST >/dev/null
+	$COMMAND -r -d $WORKDIR -D $TEST >/dev/null
 }
 
 # This is used to verify special handling for /etc/mail/aliases and
@@ -122,7 +126,7 @@ MAILER-DAEMON: postmaster
 postmaster: foo
 EOF
 
-	etcupdate -r -d $WORKDIR -D $TEST >/dev/null
+	$COMMAND -r -d $WORKDIR -D $TEST >/dev/null
 }
 
 # $1 - relative path to file that should be missing from TEST
@@ -201,7 +205,7 @@ build_login_conflict
 
 # Verify that 'p' doesn't do anything.
 echo "Checking 'p':"
-echo 'p' | etcupdate resolve -d $WORKDIR -D $TEST >/dev/null
+echo 'p' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
 
 file /etc/login.conf "" 95de92ea3f1bb1bf4f612a8b5908cddd
 missing /etc/login.conf.db
@@ -209,7 +213,7 @@ conflict /etc/login.conf
 
 # Verify that 'mf' removes the conflict, but does nothing else.
 echo "Checking 'mf':"
-echo 'mf' | etcupdate resolve -d $WORKDIR -D $TEST >/dev/null
+echo 'mf' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
 
 file /etc/login.conf "" 95de92ea3f1bb1bf4f612a8b5908cddd
 missing /etc/login.conf.db
@@ -219,7 +223,7 @@ build_login_conflict
 
 # Verify that 'tf' installs the new version of the file.
 echo "Checking 'tf':"
-echo 'tf' | etcupdate resolve -d $WORKDIR -D $TEST >/dev/null
+echo 'tf' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
 
 file /etc/login.conf "" 7774a0f9a3a372c7c109c32fd31c4b6b
 file /etc/login.conf.db
@@ -238,7 +242,7 @@ default:\\
         :welcome=/etc/motd:
 EOF
 
-echo 'r' | etcupdate resolve -d $WORKDIR -D $TEST >/dev/null
+echo 'r' | $COMMAND resolve -d $WORKDIR -D $TEST >/dev/null
 
 file /etc/login.conf "" 966e25984b9b63da8eaac8479dcb0d4d
 file /etc/login.conf.db
@@ -248,12 +252,12 @@ build_aliases_conflict
 
 # Verify that 'p' and 'mf' do not generate the newaliases warning.
 echo "Checking newalias warning for 'p'":
-echo 'p' | etcupdate resolve -d $WORKDIR -D $TEST | grep -q newalias
+echo 'p' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
 if [ $? -eq 0 ]; then
 	echo "+ Extra warning"
 fi
 echo "Checking newalias warning for 'mf'":
-echo 'mf' | etcupdate resolve -d $WORKDIR -D $TEST | grep -q newalias
+echo 'mf' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
 if [ $? -eq 0 ]; then
 	echo "+ Extra warning"
 fi
@@ -261,14 +265,14 @@ fi
 # Verify that 'tf' and 'r' do generate the newaliases warning.
 build_aliases_conflict
 echo "Checking newalias warning for 'tf'":
-echo 'tf' | etcupdate resolve -d $WORKDIR -D $TEST | grep -q newalias
+echo 'tf' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
 if [ $? -ne 0 ]; then
 	echo "- Missing warning"
 fi
 
 build_aliases_conflict
 cp $TEST/etc/mail/aliases $CONFLICTS/etc/mail/aliases
-echo 'r' | etcupdate resolve -d $WORKDIR -D $TEST | grep -q newalias
+echo 'r' | $COMMAND resolve -d $WORKDIR -D $TEST | grep -q newalias
 if [ $? -ne 0 ]; then
 	echo "- Missing warning"
 fi

Modified: stable/9/tools/regression/usr.sbin/etcupdate/fbsdid.sh
==============================================================================
--- head/tools/regression/usr.sbin/etcupdate/fbsdid.sh	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/tools/regression/usr.sbin/etcupdate/fbsdid.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -33,13 +33,17 @@ WORKDIR=work
 
 usage()
 {
-	echo "Usage: fbsdid.sh [-w workdir]"
+	echo "Usage: fbsdid.sh [-s script] [-w workdir]"
 	exit 1
 }
 
-# Allow the user to specify an alternate work directory.
-while getopts "w:" option; do
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
 	case $option in
+		s)
+			COMMAND="sh $OPTARG"
+			;;
 		w)
 			WORKDIR=$OPTARG
 			;;
@@ -191,6 +195,17 @@ EOF
 
 these are some local mods to the file
 EOF
+
+	# local-remove: A file removed locally changed it's FreeBSD ID
+	# but nothing else
+	store_id $OLD/local-remove ": head/local-remove 12000 jhb "
+	store_id $NEW/local-remove ": head/local-remove 12345 jhb "
+	for i in $OLD $NEW; do
+		cat >> $i/local-remove <<EOF
+
+this is a file
+EOF
+	done
 }
 
 # $1 - relative path to file that should be missing from TEST
@@ -267,7 +282,7 @@ fi
 
 build_trees
 
-etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
 
 cat > $WORKDIR/correct.out <<EOF
   C /already
@@ -278,6 +293,7 @@ cat > $WORKDIR/correct.out <<EOF
   C /add
 Warnings:
   Modified regular file remains: /remove
+  Removed file changed: /local-remove
 EOF
 
 echo "Differences for regular:"
@@ -295,12 +311,13 @@ conflict /conflict 868452f666fea1c60ffb9
 file /local "" aa33e614b5e749449f230e2a2b0072eb
 conflict /local 3df93e64043c8e348fc625b93ea220f4
 file /local-already "" 0298b958a603049f45ae6a109c4f7fea
+missing /local-remove
 
 # Now test with -F.
 
 build_trees
 
-etcupdate -rF -d $WORKDIR -D $TEST > $WORKDIR/testF.out
+$COMMAND -rF -d $WORKDIR -D $TEST > $WORKDIR/testF.out
 
 cat > $WORKDIR/correctF.out <<EOF
   D /remove
@@ -325,3 +342,38 @@ file /conflict "" dc27978df125b0daeb7d9b
 conflict /conflict 868452f666fea1c60ffb918ad9ad9607
 file /local "" 3ed5a35e380c8a93fb5f599d4c052713
 file /local-already "" 0298b958a603049f45ae6a109c4f7fea
+missing /local-remove
+
+# Now test with -F and -A forcing all installs.  (-A should have
+# precedence over -F)
+
+build_trees
+
+$COMMAND -A '/*' -rF -d $WORKDIR -D $TEST > $WORKDIR/testAF.out
+
+cat > $WORKDIR/correctAF.out <<EOF
+  D /remove
+  U /already
+  U /conflict
+  U /local
+  U /local-already
+  A /local-remove
+  U /old
+  U /add
+EOF
+
+echo "Differences for -A '/*' -F:"
+diff -u -L "correct" $WORKDIR/correctAF.out -L "test" $WORKDIR/testAF.out
+
+missing /remove
+file /old "" 6a9f34f109d94406a4de3bc5d72de259
+noconflict /old
+file /already "" 21f4eca3aacc702c49878c8da7afd3d0
+noconflict /already
+file /add "" 0208bd647111fedf6318511712ab9e97
+noconflict /add
+file /conflict "" 75ee141c4136beaf14e39de92efa84e4
+noconflict /conflict
+file /local "" 6a8fc5c2755b7a49015089f5e1dbe092
+file /local-already "" 49045f8b51542dd634655301cd296f66
+file /local-remove "" 5c38322efed4014797d7127f5c652d9d

Modified: stable/9/tools/regression/usr.sbin/etcupdate/ignore.sh
==============================================================================
--- head/tools/regression/usr.sbin/etcupdate/ignore.sh	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/tools/regression/usr.sbin/etcupdate/ignore.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -33,13 +33,17 @@ WORKDIR=work
 
 usage()
 {
-	echo "Usage: ignore.sh [-w workdir]"
+	echo "Usage: ignore.sh [-s script] [-w workdir]"
 	exit 1
 }
 
-# Allow the user to specify an alternate work directory.
-while getopts "w:" option; do
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
 	case $option in
+		s)
+			COMMAND="sh $OPTARG"
+			;;
 		w)
 			WORKDIR=$OPTARG
 			;;
@@ -172,7 +176,7 @@ fi
 
 build_trees
 
-etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
 
 cat > $WORKDIR/correct.out <<EOF
   D /rmdir/file
@@ -195,7 +199,7 @@ missing /rmdir
 
 build_trees
 
-etcupdate -r -I '/tree/*' -d $WORKDIR -D $TEST > $WORKDIR/test1.out
+$COMMAND -r -I '/tree/*' -d $WORKDIR -D $TEST > $WORKDIR/test1.out
 
 cat > $WORKDIR/correct1.out <<EOF
   D /rmdir/file
@@ -215,7 +219,7 @@ missing /rmdir
 
 build_trees
 
-etcupdate -r -I '/tree/*' -I '/rmdir*' -d $WORKDIR -D $TEST > \
+$COMMAND -r -I '/tree/*' -I '/rmdir*' -d $WORKDIR -D $TEST > \
     $WORKDIR/test2.out
 
 cat > $WORKDIR/correct2.out <<EOF
@@ -236,7 +240,7 @@ file /rmdir/file "foo"
 
 build_trees
 
-etcupdate -r -I '/tree/* /rmdir/*' -d $WORKDIR -D $TEST > \
+$COMMAND -r -I '/tree/* /rmdir/*' -d $WORKDIR -D $TEST > \
     $WORKDIR/test3.out
 
 cat > $WORKDIR/correct3.out <<EOF

Copied and modified: stable/9/tools/regression/usr.sbin/etcupdate/preworld.sh (from r258066, head/tools/regression/usr.sbin/etcupdate/preworld.sh)
==============================================================================
--- head/tools/regression/usr.sbin/etcupdate/preworld.sh	Tue Nov 12 19:44:18 2013	(r258066, copy source)
+++ stable/9/tools/regression/usr.sbin/etcupdate/preworld.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -66,7 +66,7 @@ TEST=$WORKDIR/test
 build_trees()
 {
 
-	# Populate trees with pre-world files and an additional file
+	# Populate trees with pre-world files and additional files
 	# that should not be touched.
 
 	rm -rf $SRC $OLD $TEST $CONFLICTS
@@ -126,6 +126,7 @@ polkit:*:562:
 haldaemon:*:560:
 EOF
 	rm $TEST/etc/inetd.conf
+	touch $TEST/etc/localtime
 
 	# Copy the "old" source tree to the new source tree and
 	# make upstream modifications.

Modified: stable/9/tools/regression/usr.sbin/etcupdate/tests.sh
==============================================================================
--- head/tools/regression/usr.sbin/etcupdate/tests.sh	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/tools/regression/usr.sbin/etcupdate/tests.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -33,13 +33,17 @@ WORKDIR=work
 
 usage()
 {
-	echo "Usage: tests.sh [-w workdir]"
+	echo "Usage: tests.sh [-s script] [-w workdir]"
 	exit 1
 }
 
-# Allow the user to specify an alternate work directory.
-while getopts "w:" option; do
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
 	case $option in
+		s)
+			COMMAND="sh $OPTARG"
+			;;
 		w)
 			WORKDIR=$OPTARG
 			;;
@@ -624,6 +628,24 @@ root: someone at example.com
 MAILER-DAEMON: postmaster
 postmaster: root
 EOF
+
+	# - Verify that updating an unmodified /etc/services builds
+	# /var/db/services.db.
+	cat > $OLD/etc/services <<EOF
+rtmp		  1/ddp	   #Routing Table Maintenance Protocol
+tcpmux		  1/tcp	   #TCP Port Service Multiplexer
+tcpmux		  1/udp	   #TCP Port Service Multiplexer
+EOF
+	cat > $NEW/etc/services <<EOF
+rtmp		  1/ddp	   #Routing Table Maintenance Protocol
+tcpmux		  1/tcp	   #TCP Port Service Multiplexer
+tcpmux		  1/udp	   #TCP Port Service Multiplexer
+nbp		  2/ddp	   #Name Binding Protocol
+compressnet	  2/tcp	   #Management Utility
+compressnet	  2/udp	   #Management Utility
+EOF
+	cp $OLD/etc/services $TEST/etc/services
+	mkdir -p $TEST/var/db
 }
 
 # $1 - relative path to file that should be missing from TEST
@@ -892,6 +914,8 @@ check_trees()
 	file /etc/login.conf "" 7774a0f9a3a372c7c109c32fd31c4b6b
 	file /etc/login.conf.db
 	file /etc/mail/aliases "" 7d598f89ec040ab56af54011bdb83337
+	file /etc/services "" 37fb6a8d1273f3b78329d431f21d9c7d
+	file /var/db/services.db
 }
 
 if [ `id -u` -ne 0 ]; then
@@ -904,7 +928,7 @@ fi
 
 build_trees
 
-etcupdate -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
 
 cat > $WORKDIR/correct.out <<EOF
   D /dirchange/fromdir/extradir/file
@@ -930,6 +954,7 @@ cat > $WORKDIR/correct.out <<EOF
   U /dirchange/old/todir
   U /etc/login.conf
   M /etc/mail/aliases
+  U /etc/services
   A /adddir/partial/file
   A /dirchange/old/todir/file
   A /etc/master.passwd
@@ -971,7 +996,7 @@ EOF
 echo "Differences for -n:"
 diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out
 
-etcupdate -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
 
 echo "Differences for real:"
 diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out

Copied: stable/9/tools/regression/usr.sbin/etcupdate/tzsetup.sh (from r259134, head/tools/regression/usr.sbin/etcupdate/tzsetup.sh)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/9/tools/regression/usr.sbin/etcupdate/tzsetup.sh	Tue Jan 14 21:20:51 2014	(r260650, copy of r259134, head/tools/regression/usr.sbin/etcupdate/tzsetup.sh)
@@ -0,0 +1,221 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Advanced Computing Technologies LLC
+# Written by: John H. Baldwin <jhb at FreeBSD.org>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+
+# Various regression tests for the tzsetup handling in the 'update' command.
+
+WORKDIR=work
+
+usage()
+{
+	echo "Usage: tzsetup.sh [-s script] [-w workdir]"
+	exit 1
+}
+
+# Allow the user to specify an alternate work directory or script.
+COMMAND=etcupdate
+while getopts "s:w:" option; do
+	case $option in
+		s)
+			COMMAND="sh $OPTARG"
+			;;
+		w)
+			WORKDIR=$OPTARG
+			;;
+		*)
+			echo
+			usage
+			;;
+	esac
+done
+shift $((OPTIND - 1))
+if [ $# -ne 0 ]; then
+	usage
+fi
+
+CONFLICTS=$WORKDIR/conflicts
+OLD=$WORKDIR/old
+NEW=$WORKDIR/current
+TEST=$WORKDIR/test
+
+build_trees()
+{
+
+	# Build the base tree, but not /etc/localtime itself
+	local i j k
+
+	rm -rf $OLD $NEW $TEST $CONFLICTS
+	mkdir -p $OLD $NEW $TEST
+	mkdir -p $TEST/etc
+	mkdir -p $TEST/var/db
+	mkdir -p $TEST/usr/share/zoneinfo
+
+	# Create a dummy timezone file
+	echo "foo" > $TEST/usr/share/zoneinfo/foo
+
+}
+
+# $1 - relative path to file that should be missing from TEST
+missing()
+{
+	if [ -e $TEST/$1 -o -L $TEST/$1 ]; then
+		echo "File $1 should be missing"
+	fi
+}
+
+# $1 - relative path to file that should be a symlink in TEST
+# $2 - optional value of the link
+link()
+{
+	local val
+
+	if ! [ -L $TEST/$1 ]; then
+		echo "File $1 should be a link"
+	elif [ $# -gt 1 ]; then
+		val=`readlink $TEST/$1`
+		if [ "$val" != "$2" ]; then
+			echo "Link $1 should link to \"$2\""
+		fi
+	fi
+}
+
+# $1 - relative path to regular file that should be present in TEST
+# $2 - optional string that should match file contents
+# $3 - optional MD5 of the flie contents, overrides $2 if present
+file()
+{
+	local contents sum
+
+	if ! [ -f $TEST/$1 ]; then
+		echo "File $1 should be a regular file"
+	elif [ $# -eq 2 ]; then
+		contents=`cat $TEST/$1`
+		if [ "$contents" != "$2" ]; then
+			echo "File $1 has wrong contents"
+		fi
+	elif [ $# -eq 3 ]; then
+		sum=`md5 -q $TEST/$1`
+		if [ "$sum" != "$3" ]; then
+			echo "File $1 has wrong contents"
+		fi
+	fi
+}
+
+if [ `id -u` -ne 0 ]; then
+	echo "must be root"
+fi
+
+if [ -r /etc/etcupdate.conf ]; then
+	echo "WARNING: /etc/etcupdate.conf settings may break some tests."
+fi
+
+# First, test for /etc/localtime not existing
+
+build_trees
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+EOF
+
+echo "Differences for no /etc/localtime with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for no /etc/localtime:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out
+
+missing /etc/localtime
+missing /var/db/zoneinfo
+
+# Second, test for /etc/localtime being a symlink
+
+build_trees
+ln -s /dev/null $TEST/etc/localtime
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+EOF
+
+echo "Differences for symlinked /etc/localtime with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for symlinked /etc/localtime:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out
+
+link /etc/localtime "/dev/null"
+missing /var/db/zoneinfo
+
+# Third, test for /etc/localtime as a file and a missing /var/db/zoneinfo
+
+build_trees
+echo "bar" > $TEST/etc/localtime
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+Warnings:
+  Needs update: /etc/localtime (required manual update via tzsetup(1))
+EOF
+
+echo "Differences for missing /var/db/zoneinfo with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for missing /var/db/zoneinfo:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out
+
+file /etc/localtime "bar"
+missing /var/db/zoneinfo
+
+# Finally, test the case where it should update /etc/localtime
+
+build_trees
+echo "bar" > $TEST/etc/localtime
+echo "foo" > $TEST/var/db/zoneinfo
+
+$COMMAND -nr -d $WORKDIR -D $TEST > $WORKDIR/testn.out
+
+cat > $WORKDIR/correct.out <<EOF
+EOF
+
+echo "Differences for real update with -n:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/testn.out
+
+$COMMAND -r -d $WORKDIR -D $TEST > $WORKDIR/test.out
+
+echo "Differences for real update:"
+diff -u -L "correct" $WORKDIR/correct.out -L "test" $WORKDIR/test.out
+
+file /etc/localtime "foo"
+file /var/db/zoneinfo "foo"

Modified: stable/9/usr.sbin/Makefile
==============================================================================
--- stable/9/usr.sbin/Makefile	Tue Jan 14 21:06:44 2014	(r260649)
+++ stable/9/usr.sbin/Makefile	Tue Jan 14 21:20:51 2014	(r260650)
@@ -24,6 +24,7 @@ SUBDIR=	adduser \
 	digictl \
 	diskinfo \
 	dumpcis \
+	etcupdate \
 	extattr \
 	extattrctl \
 	fifolog \

Modified: stable/9/usr.sbin/etcupdate/etcupdate.8
==============================================================================
--- head/usr.sbin/etcupdate/etcupdate.8	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/usr.sbin/etcupdate/etcupdate.8	Tue Jan 14 21:20:51 2014	(r260650)
@@ -1,4 +1,4 @@
-.\" Copyright (c) 2010-2012 Advanced Computing Technologies LLC
+.\" Copyright (c) 2010-2013 Advanced Computing Technologies LLC
 .\" Written by: John H. Baldwin <jhb at FreeBSD.org>
 .\" All rights reserved.
 .\"
@@ -25,7 +25,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd March 16, 2012
+.Dd December 9, 2013
 .Dt ETCUPDATE 8
 .Os
 .Sh NAME
@@ -33,7 +33,7 @@
 .Nd "manage updates to system files not updated by installworld"
 .Sh SYNOPSIS
 .Nm
-.Op Fl nBF
+.Op Fl npBF
 .Op Fl d Ar workdir
 .Op Fl r | Fl s Ar source | Fl t Ar tarball
 .Op Fl A Ar patterns
@@ -64,6 +64,7 @@
 .Op Fl M Ar options
 .Nm
 .Cm resolve
+.Op Fl p
 .Op Fl d Ar workdir
 .Op Fl D Ar destdir
 .Op Fl L Ar logfile
@@ -112,7 +113,6 @@ The
 utility will not perform a new merge until all conflicts from an earlier
 merge are resolved.
 .Sh MODES
-.Pp
 The
 .Nm
 utility supports several modes of operation.
@@ -150,7 +150,7 @@ tree.
 An older
 .Dq previous
 tree is removed if it exists.
-By default the new 
+By default the new
 .Dq current
 tree is built from a source tree.
 However,
@@ -343,25 +343,7 @@ then nothing will be output.
 .Sh OPTIONS
 The following options are available.
 Note that most options do not apply to all modes.
-.Bl -tag -width ".Fl d Ar workdir"
-.It Fl B
-Do not build generated files in a private object tree.
-Instead,
-reuse the generated files from a previously built object tree that matches
-the source tree.
-This can be useful to avoid gratuitous conflicts in sendmail configuration
-files when bootstrapping.
-It can also be useful for building a tarball that matches a specific
-world build.
-.It Fl d Ar workdir
-Specify an alternate directory to use as the work directory.
-The work directory is used to store the
-.Dq current
-and
-.Dq previous
-trees as well as unresolved conflicts.
-The default work directory is
-.Pa <destdir>/var/db/etcupdate .
+.Bl -tag -width ".Fl A Ar patterns"
 .It Fl A Ar patterns
 Always install the new version of any files that match any of the patterns
 listed in
@@ -377,9 +359,20 @@ Note that ignored files specified via th
 variable or the
 .Fl I
 option will not be installed.
+.It Fl B
+Do not build generated files in a private object tree.
+Instead,
+reuse the generated files from a previously built object tree that matches
+the source tree.
+This can be useful to avoid gratuitous conflicts in
+.Xr sendmail 8
+configuration
+files when bootstrapping.
+It can also be useful for building a tarball that matches a specific
+world build.
 .It Fl D Ar destdir
 Specify an alternate destination directory as the target of a merge.
-This is analagous to the
+This is analogous to the
 .Dv DESTDIR
 variable used with
 .Sq make installworld .
@@ -387,6 +380,15 @@ The default destination directory is an 
 merges updating
 .Pa /etc
 on the local machine.
+.It Fl d Ar workdir
+Specify an alternate directory to use as the work directory.
+The work directory is used to store the
+.Dq current
+and
+.Dq previous
+trees as well as unresolved conflicts.
+The default work directory is
+.Pa <destdir>/var/db/etcupdate .
 .It Fl F
 Ignore changes in the FreeBSD ID string when comparing files in the
 destination directory to files in either of the
@@ -480,6 +482,33 @@ option is not specified,
 then a temporary
 .Dq current
 tree will be extracted to perform the comparison.
+.It Fl p
+Enable
+.Dq pre-world
+mode.
+Only merge changes to files that are necessary to successfully run
+.Sq make installworld
+or
+.Sq make installkernel .
+When this flag is enabled,
+the existing
+.Dq current
+and
+.Dq previous
+trees are left alone.
+Instead,
+a temporary tree is populated with the necessary files.
+This temporary tree is compared against the
+.Dq current
+tree.
+This allows a normal update to be run after
+.Sq make installworld
+has completed.
+Any conflicts generated during a
+.Dq pre-world
+update should be resolved by a
+.Dq pre-world
+.Cm resolve .
 .It Fl r
 Do not update the
 .Dq current
@@ -666,6 +695,25 @@ has been removed from the
 tree,
 but it has been locally modified.
 The modified version of the file remains in the destination directory.
+.It "Needs update: /etc/localtime (required manual update via tzsetup(1))"
+The
+.Fa /var/db/zoneinfo
+file does not exist,
+so
+.Nm
+was not able to refresh
+.Fa /etc/localtime
+from its source file in
+.Fa /usr/share/zoneinfo .
+Running
+.Xr tzsetup 1
+will both refresh
+.Fa /etc/localtime
+and generate
+.Fa /var/db/zoneinfo
+permitting future updates to refresh
+.Fa /etc/localtime
+automatically.
 .It "Needs update: /etc/mail/aliases.db (required manual update via newaliases(1))"
 The file
 .Pa /etc/mail/aliases
@@ -739,12 +787,16 @@ but it has been removed in the destinati
 .El
 .Sh SEE ALSO
 .Xr cap_mkdb 1 ,
-.Xr diff 1 , 
+.Xr diff 1 ,
 .Xr make 1 ,
 .Xr newaliases 1 ,
 .Xr sh 1 ,
 .Xr pwd_mkdb 8
-.\".Sh HISTORY
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 10.0 .
 .Sh AUTHORS
 The
 .Nm

Modified: stable/9/usr.sbin/etcupdate/etcupdate.sh
==============================================================================
--- head/usr.sbin/etcupdate/etcupdate.sh	Fri Jul 13 13:23:48 2012	(r238423)
+++ stable/9/usr.sbin/etcupdate/etcupdate.sh	Tue Jan 14 21:20:51 2014	(r260650)
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2010 Advanced Computing Technologies LLC
+# Copyright (c) 2010-2013 Advanced Computing Technologies LLC
 # Written by: John H. Baldwin <jhb at FreeBSD.org>
 # All rights reserved.
 #
@@ -61,14 +61,15 @@
 usage()
 {
 	cat <<EOF
-usage: etcupdate [-nBF] [-d workdir] [-r | -s source | -t tarball] [-A patterns]
-                 [-D destdir] [-I patterns] [-L logfile] [-M options]
+usage: etcupdate [-npBF] [-d workdir] [-r | -s source | -t tarball]
+                 [-A patterns] [-D destdir] [-I patterns] [-L logfile]
+                 [-M options]
        etcupdate build [-B] [-d workdir] [-s source] [-L logfile] [-M options]
                  <tarball>
        etcupdate diff [-d workdir] [-D destdir] [-I patterns] [-L logfile]
        etcupdate extract [-B] [-d workdir] [-s source | -t tarball] [-L logfile]
                  [-M options]
-       etcupdate resolve [-d workdir] [-D destdir] [-L logfile]
+       etcupdate resolve [-p] [-d workdir] [-D destdir] [-L logfile]
        etcupdate status [-d workdir] [-D destdir]
 EOF
 	exit 1
@@ -181,22 +182,31 @@ always_install()
 # $1 - directory to store new tree in
 build_tree()
 {
-	local make
+	local destdir dir file make
 
 	make="make $MAKE_OPTIONS"
 
 	log "Building tree at $1 with $make"
 	mkdir -p $1/usr/obj >&3 2>&1
-	(cd $SRCDIR; $make DESTDIR=$1 distrib-dirs) >&3 2>&1 || return 1
+	destdir=`realpath $1`
 
-	if ! [ -n "$nobuild" ]; then
-		(cd $SRCDIR; \
-	    MAKEOBJDIRPREFIX=$1/usr/obj $make _obj SUBDIR_OVERRIDE=etc &&
-	    MAKEOBJDIRPREFIX=$1/usr/obj $make everything SUBDIR_OVERRIDE=etc &&
-	    MAKEOBJDIRPREFIX=$1/usr/obj $make DESTDIR=$1 distribution) \
+	if [ -n "$preworld" ]; then
+		# Build a limited tree that only contains files that are
+		# crucial to installworld.
+		for file in $PREWORLD_FILES; do
+			dir=`dirname /$file`
+			mkdir -p $1/$dir >&3 2>&1 || return 1
+			cp -p $SRCDIR/$file $1/$file || return 1
+		done
+	elif ! [ -n "$nobuild" ]; then
+		(cd $SRCDIR; $make DESTDIR=$destdir distrib-dirs &&
+    MAKEOBJDIRPREFIX=$destdir/usr/obj $make _obj SUBDIR_OVERRIDE=etc &&
+    MAKEOBJDIRPREFIX=$destdir/usr/obj $make everything SUBDIR_OVERRIDE=etc &&
+    MAKEOBJDIRPREFIX=$destdir/usr/obj $make DESTDIR=$destdir distribution) \
 		    >&3 2>&1 || return 1
 	else
-		(cd $SRCDIR; $make DESTDIR=$1 distribution) >&3 2>&1 || return 1
+		(cd $SRCDIR; $make DESTDIR=$destdir distrib-dirs &&
+		    $make DESTDIR=$destdir distribution) >&3 2>&1 || return 1
 	fi
 	chflags -R noschg $1 >&3 2>&1 || return 1
 	rm -rf $1/usr/obj >&3 2>&1 || return 1
@@ -218,9 +228,15 @@ build_tree()
 # source tree.
 extract_tree()
 {
+	local files
+
 	# If we have a tarball, extract that into the new directory.
 	if [ -n "$tarball" ]; then
-		if ! (mkdir -p $NEWTREE && tar xf $tarball -C $NEWTREE) \
+		files=
+		if [ -n "$preworld" ]; then
+			files="$PREWORLD_FILES"
+		fi
+		if ! (mkdir -p $NEWTREE && tar xf $tarball -C $NEWTREE $files) \
 		    >&3 2>&1; then
 			echo "Failed to extract new tree."
 			remove_tree $NEWTREE
@@ -470,6 +486,39 @@ diffnode()
 	esac
 }
 
+# Run one-off commands after an update has completed.  These commands
+# are not tied to a specific file, so they cannot be handled by
+# post_install_file().
+post_update()
+{
+	local args
+
+	# None of these commands should be run for a pre-world update.
+	if [ -n "$preworld" ]; then
+		return
+	fi
+
+	# If /etc/localtime exists and is not a symlink and /var/db/zoneinfo
+	# exists, run tzsetup -r to refresh /etc/localtime.
+	if [ -f ${DESTDIR}/etc/localtime -a \
+	    ! -L ${DESTDIR}/etc/localtime ]; then
+		if [ -f ${DESTDIR}/var/db/zoneinfo ]; then
+			if [ -n "${DESTDIR}" ]; then
+				args="-C ${DESTDIR}"
+			else
+				args=""
+			fi
+			log "tzsetup -r ${args}"
+			if [ -z "$dryrun" ]; then
+				tzsetup -r ${args} >&3 2>&1
+			fi
+		else
+			warn "Needs update: /etc/localtime (required" \
+			    "manual update via tzsetup(1))"
+		fi
+	fi
+}
+
 # Create missing parent directories of a node in a target tree
 # preserving the owner, group, and permissions from a specified
 # template tree.
@@ -567,6 +616,14 @@ post_install_file()
 				fi
 			fi
 			;;
+		/etc/services)
+			log "services_mkdb -q -o $DESTDIR/var/db/services.db" \
+			    "${DESTDIR}$1"
+			if [ -z "$dryrun" ]; then
+				services_mkdb -q -o $DESTDIR/var/db/services.db \
+				    ${DESTDIR}$1 >&3 2>&1
+			fi
+			;;
 	esac
 }
 
@@ -1010,16 +1067,6 @@ handle_modified_file()
 		fi
 	fi
 
-	# If the only change in the new file versus the old file is a
-	# change in the FreeBSD ID string and -F is specified, just
-	# update the FreeBSD ID string in the local file.

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-stable-9 mailing list