Module Name:    src
Committed By:   apb
Date:           Thu Jun 12 13:56:32 UTC 2014

Modified Files:
        src/usr.sbin/etcupdate: etcupdate etcupdate.8

Log Message:
Add "-d destdir" option to etcupdate.
This has been only lightly tested.


To generate a diff of this commit:
cvs rdiff -u -r1.55 -r1.56 src/usr.sbin/etcupdate/etcupdate
cvs rdiff -u -r1.20 -r1.21 src/usr.sbin/etcupdate/etcupdate.8

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.sbin/etcupdate/etcupdate
diff -u src/usr.sbin/etcupdate/etcupdate:1.55 src/usr.sbin/etcupdate/etcupdate:1.56
--- src/usr.sbin/etcupdate/etcupdate:1.55	Thu Jun 12 13:42:05 2014
+++ src/usr.sbin/etcupdate/etcupdate	Thu Jun 12 13:56:32 2014
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# $NetBSD: etcupdate,v 1.55 2014/06/12 13:42:05 apb Exp $
+# $NetBSD: etcupdate,v 1.56 2014/06/12 13:56:32 apb Exp $
 #
 # Copyright (c) 2001-2008 The NetBSD Foundation, Inc.
 # All rights reserved.
@@ -46,6 +46,8 @@ PATH="/sbin:/usr/sbin:/bin:/usr/bin:${PA
 
 # Default settings
 PROG="${0##*/}"
+DESTDIR=""		# must not have a trailing slash
+DESTDIR_BRE=""		# basic regex to match ${DESTDIR}
 TEMPROOT="${TEMPROOT:=/tmp/temproot}"
 PAGER="${PAGER:=/usr/bin/more}"
 SWIDTH="$(stty size | awk '{w=$2}END{if(w==0){w=80}print w}')"
@@ -60,7 +62,7 @@ BINARYDIRMODE=false	# true for "-s extra
 BINARYDIR=		# directory name for BINARYDIRMODE
 BINARYTGZMODE=false	# true for "-s etc.tgz"
 TGZLIST=		# quoted list list of files for BINARYTGZMODE
-SRC_ARGLIST=		# quoted list of one or more "-s" args
+SRC_ARGLIST=		# quoted list of "-s" args
 N_SRC_ARGS=0		# number of "-s" args
 AUTOMATIC=false
 LOCALSKIP=false
@@ -95,6 +97,7 @@ Options:
                * A temporary directory in which one or both of "etc.tgz"
                  and "xetc.tgz" have been extracted.
   -t temproot  Where to store temporary files  (default: /tmp/temproot)
+  -d destdir   Destination directory to check. (default: /)
   -w width     Screen width                    (default: 80)
   -a           Automatically update unmodified files
   -l           Automatically skip files with strictly local changes
@@ -151,24 +154,38 @@ shell_quote()
 	printf "%s\n" "$result"
 }
 
+# Convert arg $1 to a basic regular expression (as in sed)
+# that will match the arg.  This works by inserting backslashes
+# before characters that are special in basic regular expressions.
+# It also inserts backslashes before the extra characters specified
+# in $2 (which defaults to "/,").
+# XXX: Does not handle embedded newlines.
+# Usage: regex="$(bre_quote "${string}")"
+bre_quote()
+{
+	local arg="$1"
+	local extra="$2:/,"
+	printf "%s\n" "${arg}" | sed -e 's/[][^$.*\\'"${extra}"']/\\&/g'
+}
+
 install_dir() {
-	# $1 = target directory
+	# $1 = target directory (relative to ${DESTDIR})
 
 	NEED_ANYTHING=true
-	if yesno "Create ${1}"; then
-		verbose "Creating ${1}"
-		mkdir -p "${1}" || exit 1
+	if yesno "Create ${DESTDIR}${1}"; then
+		verbose "Creating ${DESTDIR}${1}"
+		mkdir -p "${DESTDIR}${1}" || exit 1
 		NEED_MTREE=true
 	fi
 }
 
 install_file() {
-	# $1 = target file
+	# $1 = target file (relative to ${DESTDIR})
 
 	NEED_ANYTHING=true
 	# Install the new file
-	verbose "Installing ${1}"
-	cp -p "${TEMPROOT}${1}" "${1}" && rm -f "${TEMPROOT}${1}"
+	verbose "Installing ${DESTDIR}${1}"
+	cp -p "${TEMPROOT}${1}" "${DESTDIR}${1}" && rm -f "${TEMPROOT}${1}"
 
 	# Check if this was a special file
 	case "${1}" in
@@ -191,15 +208,20 @@ install_file() {
 }
 
 install_checksum() {
-	# $1 = target file
+	# $1 = target file (relative to ${DESTDIR})
 
 	${AUTOMATIC} || return
 
 	NEED_ANYTHING=true
 	D="$(dirname "${1}")"
-	mkdir -p "/var/etcupdate/${D}"
-	verbose "Saving MD5 checksum for ${1} to /var/etcupdate/${1}"
-	md5 "${1}" > "/var/etcupdate/${1}"
+	mkdir -p "${DESTDIR}/var/etcupdate/${D}"
+	verbose "Saving MD5 checksum for ${DESTDIR}${1} to" \
+	    "${DESTDIR}/var/etcupdate/${1}"
+	# The sed part of the following pipeline changes things like
+	# "MD5 (/path/to/dest/dir/etc/filename) = abc123" to
+	# "MD5 (/etc/filename) = abc123".
+	md5 "${DESTDIR}${1}" | sed -e "s,(${DESTDIR_BRE},(," \
+	    > "${DESTDIR}/var/etcupdate/${1}"
 }
 
 # Initialise the DIFF_EXTRA_OPTIONS variable.
@@ -230,18 +252,18 @@ init_diff_extra_options() {
 }
 
 diff_and_merge_file() {
-	# $1 = target file
+	# $1 = target file (relative to ${DESTDIR})
 
-	if cmp -s "${TEMPROOT}${1}" "${1}"; then
+	if cmp -s "${TEMPROOT}${1}" "${DESTDIR}${1}"; then
 		verbose "===> ${1} (ok)"
 		rm -f "${TEMPROOT}${1}"
-		install_checksum "${1}"
+		install_checksum "${DESTDIR}${1}"
 		return
 	fi
 
-	if ${AUTOMATIC} && [ -f "/var/etcupdate/${1}" ]; then
+	if ${AUTOMATIC} && [ -f "${DESTDIR}/var/etcupdate/${1}" ]; then
 		SUM1="$(md5 "${1}")"
-		SUM2="$(cat "/var/etcupdate/${1}")"
+		SUM2="$(cat "${DESTDIR}/var/etcupdate/${1}")"
 		if [ "${SUM1}" = "${SUM2}" ]; then
 			install_file "${1}"
 			install_checksum "${1}"
@@ -252,7 +274,7 @@ diff_and_merge_file() {
 	if ${LOCALSKIP}; then
 		ID1="$(ident -q "${TEMPROOT}${1}" | sed -n 2p)"
 		ID1="${ID1:-0}"
-		ID2="$(ident -q "${1}" | sed -n 2p)"
+		ID2="$(ident -q "${DESTDIR}${1}" | sed -n 2p)"
 		ID2="${ID2:-1}"
 		if [ "${ID1}" = "${ID2}" ]; then
 			verbose "===> ${1} (ok:RCS)"
@@ -262,14 +284,14 @@ diff_and_merge_file() {
 	fi
 
 	clear
-	if [ ! -f "${1}" ]; then
-		verbose "===> ${1} (missing)"
+	if [ ! -f "${DESTDIR}${1}" ]; then
+		verbose "===> ${DESTDIR}${1} (missing)"
 		DOES_EXIST=false
 	else
-		verbose "===> ${1} (modified)"
+		verbose "===> ${DESTDIR}${1} (modified)"
 		verbose ""
 		DOES_EXIST=true
-		diff -u "${1}" "${TEMPROOT}${1}" | ${PAGER}
+		diff -u "${DESTDIR}${1}" "${TEMPROOT}${1}" | ${PAGER}
 	fi
 
 	STAY_HERE=true
@@ -286,8 +308,8 @@ diff_and_merge_file() {
 		# Ask the user if (s)he wants to install the new
 		# version or perform a more complicated manual work.
 		echo ""
-		echo -n "File: ${1}"
-		if [ ! -f "${1}" ]; then
+		echo -n "File: ${DESTDIR}${1}"
+		if [ ! -f "${DESTDIR}${1}" ]; then
 			echo -n " (missing)"
 		else
 			echo -n " (modified)"
@@ -348,7 +370,7 @@ EOF
 			sdiff -o "${TEMPROOT}${1}.merged"	\
 				--width=${WIDTH}		\
 				--suppress-common-lines --text	\
-				"${1}" "${TEMPROOT}${1}"
+				"${DESTDIR}${1}" "${TEMPROOT}${1}"
 			mv -f "${TEMPROOT}${1}.merged" "${TEMPROOT}${1}"
 			ALREADY_MERGED=true
 			;;
@@ -362,7 +384,8 @@ EOF
 			[sS]w)	DIFF_COMMAND="wdiff -n -l" ;;
 			[sS]*)	DIFF_COMMAND="${ANSWER#?}" ;;
 			esac
-			${DIFF_COMMAND} "${1}" "${TEMPROOT}${1}" | ${PAGER}
+			${DIFF_COMMAND} "${DESTDIR}${1}" "${TEMPROOT}${1}" \
+				| ${PAGER}
 			;;
 		[uU])
 			if [ -f "${B}" ]; then
@@ -416,12 +439,15 @@ USERRC="${HOME}/.{PROG}rc"
 [ -r ${USERRC} ] && . ${USERRC}
 
 # Read command line arguments
-while getopts ahlp:s:t:vw: i
+while getopts ad:hlp:s:t:vw: i
 do
 	case "${i}" in
 	a)
 		AUTOMATIC=true
 		;;
+	d)
+		DESTDIR="${OPTARG}"
+		;;
 	h)
 		usage
 		;;
@@ -487,6 +513,8 @@ if [ "$(id -u)" -ne 0 ]; then
 	echo "*** ERROR: You MUST be root"
 	exit 1
 fi
+DESTDIR="${DESTDIR%/}" # remove trailing slash, if any.  result might be "".
+DESTDIR_BRE="$(bre_quote "${DESTDIR}")"
 if [ "${N_SRC_ARGS}" -gt 1 ] && ( ${SOURCEMODE} || ${BINARYDIRMODE} ); then
 	echo "*** ERROR: Multiple -s args are allowed only with tgz files"
 	usage
@@ -667,38 +695,46 @@ fi
 
 # Do some post-installation tasks
 if ${NEED_PWD_MKDB}; then
+	pwd_mkdb_cmd="$(shell_quote \
+	    pwd_mkdb ${DESTDIR:+-d "${DESTDIR}"} \
+	    -p "${DESTDIR}/etc/master.passwd")"
 	if yesno "Do you want to rebuild the password databases from the" \
-	         "new master.passwd"
+	         "new ${DESTDIR}/etc/master.passwd"
 	then
 		verbose "Running pwd_mkdb"
-		pwd_mkdb -p "/etc/master.passwd"
+		eval "${pwd_mkdb_cmd}"
 	else
 		echo ""
 		echo "*** You MUST rebuild the password databases to make" \
 		     "the changes visible"
-		echo "*** This is done by running \"pwd_mkdb -p" \
-		     "/etc/master.passwd\" as root"
+		echo "*** This is done by running \"${pwd_mkdb_cmd}\" as root"
 		echo ""
 	fi
 fi
 
 if ! ${NEED_SERVICES_MKDB}; then
-	if test -e /var/db/services.db -a ! -e /var/db/services.cdb; then
+	if test -e "${DESTDIR}/var/db/services.db" \
+	   -a ! -e "${DESTDIR}/var/db/services.cdb"
+	then
 		NEED_SERVICES_MKDB=true
 	fi
 fi
 
 if ${NEED_SERVICES_MKDB}; then
+	services_mkdb_cmd="$(shell_quote services_mkdb -V cdb \
+	    -o "${DESTDIR}/var/db/services.cdb" \
+	    "${DESTDIR}/etc/services")"
 	if yesno "Do you want to rebuild the services databases from the" \
-	         "new /etc/services"
+	         "new ${DESTDIR}/etc/services"
 	then
 		verbose "Running services_mkdb"
-		services_mkdb
+		eval "${services_mkdb_cmd}"
 	else
 		echo ""
 		echo "*** You SHOULD rebuild the services databases to make" \
 		     "the changes visible"
-		echo "*** This is done by running \"services_mkdb\" as root"
+		echo "*** This is done by running \"${services_mkdb_cmd}\"" \
+		     "as root"
 		echo ""
 	fi
 fi
@@ -706,35 +742,57 @@ if ${NEED_MTREE}; then
 	if yesno "You have created new directories. Run mtree to set" \
 	         "permissions"
 	then
-		(cd / && mtree -Udef /etc/mtree/NetBSD.dist)
+		(cd "${DESTDIR:-/}" && \
+		    mtree -Udef "${DESTDIR}/etc/mtree/NetBSD.dist")
 	fi
 fi
 if ${NEED_MAKEDEV}; then
-	if yesno "Do you want to rebuild the device nodes in /dev"; then
+	makedev_cmd="($(shell_quote cd "${DESTDIR}/dev") && ./MAKEDEV all)"
+	if yesno "Do you want to rebuild the device nodes in ${DESTDIR}/dev"
+	then
 		verbose "Running MAKEDEV in /dev"
-		(cd "/dev" && ./MAKEDEV all)
+		eval "${makedev_cmd}"
 	else
 		echo ""
-		echo "*** You SHOULD rebuild the device nodes in /dev"
-		echo "*** This is done by running \"(cd /dev &&" \
-		     "./MAKEDEV all)\" as root".
+		echo "*** You SHOULD rebuild the device nodes in" \
+		     "${DESTDIR}/dev"
+		echo "*** This is done by running \"${makedev_cmd}\" as root."
 		echo ""
 	fi
 fi
 if ${NEED_NEWALIASES}; then
-	if yesno "Do you want to rebuild the mail alias database"; then
+	newaliases_cmd="newaliases"
+	# XXX newaliases doesn't work with DESTDIR.
+	# We could check whether the system configuration is
+	# sufficiently standard, and then run postalias(1) with the
+	# right args to make it work, but changes to /etc/mail/aliases
+	# are so rare that it doesn't seem worth the effort of checking
+	# that the system's mail configuration is standard.
+	if [ -z "${DESTDIR}" ] && \
+	    yesno "Do you want to rebuild the mail alias database"
+	then
 		verbose "Running newaliases"
-		newaliases
+		eval "${newaliases_cmd}"
 	else
 		echo ""
 		echo "*** You MUST rebuild the mail alias database to make" \
 		     "the changes visible"
-		echo "*** This is done by running \"newaliases\" as root"
+		echo "*** This is done by running \"${newaliases_cmd}\" as root"
+		if [ -n "${DESTDIR}" ]; then
+		    postalias_cmd="$(shell_quote \
+			postalias "hash:${DESTDIR}/etc/mail/aliases")"
+		    echo "*** but it won't work with DESTDIR=${DESTDIR}."
+		    echo "*** If you use postfix(1) with the default" \
+			 "configuration, then you can try"
+		    echo "*** running \"${postalias_cmd}\" as root."
+		fi
 		echo ""
 	fi
 fi
-if [ -x /usr/sbin/postinstall ]; then
-	echo "*** Running /usr/sbin/postinstall"
-	eval "/usr/sbin/postinstall ${SRC_ARGLIST} check"
+if [ -x "${DESTDIR}/usr/sbin/postinstall" ]; then
+	postinstall_cmd="$(shell_quote "${DESTDIR}/usr/sbin/postinstall" \
+	    ${DESTDIR:+-d "${DESTDIR}"}) ${SRC_ARGLIST} check"
+	echo "*** Running ${DESTDIR}/usr/sbin/postinstall"
+	eval "${postinstall_cmd}"
 fi
 echo "*** All done"

Index: src/usr.sbin/etcupdate/etcupdate.8
diff -u src/usr.sbin/etcupdate/etcupdate.8:1.20 src/usr.sbin/etcupdate/etcupdate.8:1.21
--- src/usr.sbin/etcupdate/etcupdate.8:1.20	Wed Aug 15 16:26:41 2012
+++ src/usr.sbin/etcupdate/etcupdate.8	Thu Jun 12 13:56:32 2014
@@ -1,4 +1,4 @@
-.\"	$NetBSD: etcupdate.8,v 1.20 2012/08/15 16:26:41 apb Exp $
+.\"	$NetBSD: etcupdate.8,v 1.21 2014/06/12 13:56:32 apb Exp $
 .\"
 .\" Copyright (c) 2001-2008 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -37,6 +37,7 @@
 .Sh SYNOPSIS
 .Nm
 .Op Fl ahlv
+.Op Fl d Ar destdir
 .Op Fl p Ar pager
 .Op Fl s Brq Ar srcdir | Ar tgzdir | Ar tgzfile
 .Op Fl t Ar temproot
@@ -136,6 +137,17 @@ to store MD5 checksums in
 .Pa /var/etcupdate
 and use these checksums to determine if there have been any
 local modifications.
+.It Fl d Ar destdir
+Use
+.Ar destdir
+instead of
+.Pa /
+as the top of the file system hierarchy to be updated.
+For example,
+.Ar destdir Ns Pa /etc
+will be used instead of
+.Pa /etc .
+.Pa \&/ .
 .It Fl h
 Prints a help text.
 .It Fl l
@@ -387,10 +399,12 @@ In
 .Nx 7.0 ,
 the ability to specify multiple colon-separated files with a single
 .Fl s
-option was removed.
-Multiple
+option was removed (multiple
 .Fl s
-options must be used instead.
+options must be used instead,
+and the
+.Fl d Ar destdir
+option was added.
 .Sh AUTHORS
 The script was written by
 .An Martti Kuparinen

Reply via email to