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