Module Name: src Committed By: tls Date: Sun Aug 10 06:59:29 UTC 2014
Modified Files: src/usr.sbin/etcupdate [tls-earlyentropy]: etcupdate etcupdate.8 Log Message: Rebase. To generate a diff of this commit: cvs rdiff -u -r1.51 -r1.51.8.1 src/usr.sbin/etcupdate/etcupdate cvs rdiff -u -r1.20 -r1.20.8.1 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.51 src/usr.sbin/etcupdate/etcupdate:1.51.8.1 --- src/usr.sbin/etcupdate/etcupdate:1.51 Wed Aug 15 16:26:41 2012 +++ src/usr.sbin/etcupdate/etcupdate Sun Aug 10 06:59:29 2014 @@ -1,6 +1,6 @@ #!/bin/sh # -# $NetBSD: etcupdate,v 1.51 2012/08/15 16:26:41 apb Exp $ +# $NetBSD: etcupdate,v 1.51.8.1 2014/08/10 06:59:29 tls 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 @@ -70,6 +72,7 @@ MACHINE_ARCH="${MACHINE_ARCH:="$(uname - export MACHINE_ARCH # Settings for post-installation procedures +NEED_ANYTHING=false NEED_MAKEDEV=false NEED_MTREE=false NEED_NEWALIASES=false @@ -94,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 @@ -134,38 +138,76 @@ yesno() { # eval "set -- $quotedlist" # or like this: # eval "\$command $quotedlist \$filename" +# shell_quote() -{ +{( local result='' - local arg + local arg qarg + LC_COLLATE=C ; export LC_COLLATE # so [a-zA-Z0-9] works in ASCII for arg in "$@" ; do - # Append a space if necessary - result="${result}${result:+ }" - # Convert each embedded ' to '\'', - # then insert ' at the beginning of the first line, - # and append ' at the end of the last line. - result="${result}$(printf "%s\n" "$arg" | \ - sed -e "s/'/'\\\\''/g" -e "1s/^/'/" -e "\$s/\$/'/")" + case "${arg}" in + '') + qarg="''" + ;; + *[!-./a-zA-Z0-9]*) + # Convert each embedded ' to '\'', + # then insert ' at the beginning of the first line, + # and append ' at the end of the last line. + # Finally, elide unnecessary '' pairs at the + # beginning and end of the result and as part of + # '\'''\'' sequences that result from multiple + # adjacent quotes in he input. + qarg="$(printf "%s\n" "$arg" | \ + ${SED:-sed} -e "s/'/'\\\\''/g" \ + -e "1s/^/'/" -e "\$s/\$/'/" \ + -e "1s/^''//" -e "\$s/''\$//" \ + -e "s/'''/'/g" + )" + ;; + *) + # Arg is not the empty string, and does not contain + # any unsafe characters. Leave it unchanged for + # readability. + qarg="${arg}" + ;; + esac + result="${result}${result:+ }${qarg}" done 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}) - if yesno "Create ${1}"; then - verbose "Creating ${1}" - mkdir -p "${1}" || exit 1 + NEED_ANYTHING=true + 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 @@ -188,14 +230,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. @@ -226,18 +274,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}" @@ -248,7 +296,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)" @@ -258,14 +306,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 @@ -282,8 +330,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)" @@ -344,7 +392,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 ;; @@ -358,7 +406,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 @@ -378,7 +427,7 @@ EOF ;; esac done - rm -f "._etcupdate_${TEMPROOT}${1}" + rm -f "$B" } # Set the environment for make. @@ -412,12 +461,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 ;; @@ -447,7 +499,7 @@ do # arg refers to a source directory SOURCEMODE=true SRCDIR="${arg}" - elif [ -d "${arg}" ] && [ -d "${ARG}/etc" ] \ + elif [ -d "${arg}" ] && [ -d "${arg}/etc" ] \ && ! [ -f "${arg}/etc/Makefile" ] then # arg refers to a directory where the @@ -456,7 +508,8 @@ do BINARYDIRMODE=true BINARYDIR="${arg}" else - echo "*** Nonexistent file or directory for -s ${arg}" + echo "*** Nonexistent or invalid file or directory" \ + "for -s ${arg}" usage fi ;; @@ -482,10 +535,19 @@ 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 fi +case "${TEMPROOT}" in +/*) : OK ;; +*) new="${PWD:-$(pwd)}/${TEMPROOT}" + echo "*** NOTE: Using TEMPROOT \"${new}\" instead of \"${TEMPROOT}\"" + TEMPROOT="${new}" + ;; +esac if ${BINARYDIRMODE}; then SRCDIR="${TEMPROOT}" fi @@ -540,10 +602,24 @@ if ! ${CONTINUE}; then [ $? -ne 0 ] && exit 1 done elif ${BINARYDIRMODE}; then - # Populate ${TEMPROOT} from ${SRCDIR} by copying + # Populate ${TEMPROOT} from ${SRCDIR} by copying. + # Copy only the files that belong to the etc and xetc sets. echo "*** Populating ${TEMPROOT} from ${BINARYDIR} (copying)" - cp -RPp "${BINARYDIR}"/* "${TEMPROOT}"/ - [ $? -ne 0 ] && exit 1 + for setname in etc xetc; do + mtreefile="${BINARYDIR}/etc/mtree/set.${setname}" + if ${VERBOSE}; then vflag="-v"; else vflag=""; fi + if [ -f "${mtreefile}" ]; then + echo "*** Copying files belonging to" \ + "${setname} set" + (cd "${BINARYDIR}" \ + && pax -rwdM ${vflag} "${TEMPROOT%/}/." + ) <"${mtreefile}" + [ $? -ne 0 ] && exit 1 + else + echo "*** Not copying files belonging to" \ + "${setname} set: ${mtreefile} not found" + fi + done elif ${SOURCEMODE}; then # Populate ${TEMPROOT} from ${SRCDIR} by running make if [ ! -f "${SRCDIR}/etc/Makefile" ]; then @@ -615,6 +691,10 @@ if [ ! -z "${REMAINING}" ]; then echo "" echo "${REMAINING}" | sed -e 's/^/ /' echo "" +elif ! ${NEED_ANYTHING}; then + echo "" + echo "*** No changes were needed" + echo "" fi if yesno "Remove ${TEMPROOT}"; then echo "*** Removing ${TEMPROOT}" @@ -637,38 +717,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 @@ -676,35 +764,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.20.8.1 --- src/usr.sbin/etcupdate/etcupdate.8:1.20 Wed Aug 15 16:26:41 2012 +++ src/usr.sbin/etcupdate/etcupdate.8 Sun Aug 10 06:59:29 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: etcupdate.8,v 1.20 2012/08/15 16:26:41 apb Exp $ +.\" $NetBSD: etcupdate.8,v 1.20.8.1 2014/08/10 06:59:29 tls Exp $ .\" .\" Copyright (c) 2001-2008 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd August 15, 2012 +.Dd June 12, 2014 .Dt ETCUPDATE 8 .Os .Sh NAME @@ -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,16 @@ 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 . .It Fl h Prints a help text. .It Fl l @@ -387,10 +398,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