Changeset View
Standalone View
usr.sbin/mergemaster/mergemaster.sh
Show First 20 Lines • Show All 347 Lines • ▼ Show 20 Lines | D) | ||||
;; | ;; | ||||
*) | *) | ||||
display_usage | display_usage | ||||
exit 1 | exit 1 | ||||
;; | ;; | ||||
esac | esac | ||||
done | done | ||||
# Resolve a potentially relative destination directory which is | |||||
# required to later catch symbolic links pointing outside of it | |||||
if [ -n "${DESTDIR}" ]; then | |||||
DESTDIR=`realpath "${DESTDIR}"` | |||||
jilles: The quoting is correct here, but there should be an error check. Otherwise, a non-existent… | |||||
if [ $? != 0 ]; then | |||||
exit 1 | |||||
fi | |||||
fi | |||||
if [ -n "$AUTO_RUN" ]; then | if [ -n "$AUTO_RUN" ]; then | ||||
if [ -n "$FREEBSD_ID" -o -n "$AUTO_UPGRADE" -o -n "$AUTO_INSTALL" ]; then | if [ -n "$FREEBSD_ID" -o -n "$AUTO_UPGRADE" -o -n "$AUTO_INSTALL" ]; then | ||||
echo '' | echo '' | ||||
echo "*** You have included the -a option along with one or more options" | echo "*** You have included the -a option along with one or more options" | ||||
echo ' that indicate that you wish mergemaster to actually make updates' | echo ' that indicate that you wish mergemaster to actually make updates' | ||||
echo ' (-F, -U, or -i), however these options are not compatible.' | echo ' (-F, -U, or -i), however these options are not compatible.' | ||||
echo ' Please read mergemaster(8) for more information.' | echo ' Please read mergemaster(8) for more information.' | ||||
echo '' | echo '' | ||||
▲ Show 20 Lines • Show All 665 Lines • ▼ Show 20 Lines | for COMPFILE in `find . | sort` ; do | ||||
fi | fi | ||||
TEMPROOT_TYPE=`stat -f '%HT' $COMPFILE` | TEMPROOT_TYPE=`stat -f '%HT' $COMPFILE` | ||||
if [ ! "$TEMPROOT_TYPE" = "$INSTALLED_TYPE" ]; then | if [ ! "$TEMPROOT_TYPE" = "$INSTALLED_TYPE" ]; then | ||||
[ "$COMPFILE" = '.' ] && continue | [ "$COMPFILE" = '.' ] && continue | ||||
TEMPROOT_TYPE=`echo $TEMPROOT_TYPE | tr [:upper:] [:lower:]` | TEMPROOT_TYPE=`echo $TEMPROOT_TYPE | tr [:upper:] [:lower:]` | ||||
INSTALLED_TYPE=`echo $INSTALLED_TYPE | tr [:upper:] [:lower:]` | INSTALLED_TYPE=`echo $INSTALLED_TYPE | tr [:upper:] [:lower:]` | ||||
# Ignore the type mismatch for user specified files if the installed | |||||
# file is of type symlink and the following conditions are met: | |||||
# - installed type is symlink | |||||
# - symlink target has the correct type | |||||
# - if DESTDIR is set, symlink does not point outside of it | |||||
# - file is listed in ALLOW_SYMLINK | |||||
# Always allow /boot to be a symlink to handle bsdinstall linking /boot | |||||
# to an unencrypted boot volume | |||||
Not Done Inline Actionsstat's -L flag can be used instead of a realpath invocation. jilles: stat's -L flag can be used instead of a realpath invocation. | |||||
Not Done Inline ActionsI can use /usr/bin/stat -f "%R" "${DESTDIR}${COMPFILE#.}" instead of /bin/realpath "${DESTDIR}${COMPFILE#.}", no problem. But since the manpage says the data for these field specifiers does not come directly from struct stat, my guess it that it calls realpath in the background. I also considered it more readable than a stat format string. Neither stat -L -f %N or stat -L -f %Y give me the absolute path pointed at by a relative symlink, which is required later to check that the symlink does not escape a changed basepath. What am I missing? code.jpe_gmail.com: I can use `/usr/bin/stat -f "%R" "${DESTDIR}${COMPFILE#.}"` instead of `/bin/realpath… | |||||
Not Done Inline ActionsOh right, you do need ${SYMLINK_TARGET} below. Ignore my comment :) jilles: Oh right, you do need `${SYMLINK_TARGET}` below. Ignore my comment :) | |||||
if [ "${INSTALLED_TYPE}" = 'symbolic link' ]; then | |||||
Not Done Inline ActionsAlthough this issue already exists in the surrounding code, ${SYMLINK_TARGET} (${DESTDIR}${COMPFILE#.} with the above comment), [:upper:] and [:lower:] should be quoted to avoid pathname generation and word splitting. jilles: Although this issue already exists in the surrounding code, `${SYMLINK_TARGET}`… | |||||
SYMLINK_TARGET=`realpath "${DESTDIR}${COMPFILE#.}"` | |||||
SYMLINK_TARGET_TYPE=`stat -f '%HT' "${SYMLINK_TARGET}" | tr "[:upper:]" "[:lower:]"` | |||||
Not Done Inline ActionsThis test checks that a string is non-empty which is definitely not empty. This is not what you seem to mean. Also, prefer a case statement or two tests with || (you will need braces) to one test with -o. jilles: This test checks that a string is non-empty which is definitely not empty. This is not what you… | |||||
Not Done Inline Actions$DESTDIR is only set if mergemaster is started with -D /different/basepath, mergemaster uses for example ${DESTDIR}/ or ${DESTDIR}/var/db to refer to / or /var/db if called without a changed base directory. This line checks if ${DESTDIR} is unset and the user has therefor not changed the basepath, or when ${DESTDIR} is set, then ${SYMLINK_TARGET} must change if ${DESTDIR} prefix is removed. If ${SYMLINK_TARGET} has no prefix that matches ${DESTDIR} and stays the same, then the symlink points outside of the argument provided basepath. code.jpe_gmail.com: `$DESTDIR` is only set if mergemaster is started with `-D /different/basepath`, mergemaster… | |||||
Not Done Inline ActionsThat's not what it actually does because the quoting is wrong ;) jilles: That's not what it actually does because the quoting is wrong ;) | |||||
if [ "${TEMPROOT_TYPE}" = "${SYMLINK_TARGET_TYPE}" ]; then | |||||
# if DESTDIR is set it must be a removable prefix of SYMLINK_TARGET | |||||
if [ -z "${DESTDIR}" ] || [ "${SYMLINK_TARGET}" != "${SYMLINK_TARGET##${DESTDIR}}" ]; then | |||||
Not Done Inline ActionsConsider case " $ALLOW_SYMLINK " in *" ${COMPFILE#.} "*) continue ;; esac The same thing for the below loop. jilles: Consider
case " $ALLOW_SYMLINK " in
*" ${COMPFILE#.} "*) continue ;;
esac
The… | |||||
case " ${ALLOW_SYMLINK} /boot " in | |||||
*" ${COMPFILE#.} "*) continue ;; | |||||
esac | |||||
fi | |||||
fi | |||||
fi | |||||
echo "*** The installed file ${DESTDIR}${COMPFILE#.} has the type \"$INSTALLED_TYPE\"" | echo "*** The installed file ${DESTDIR}${COMPFILE#.} has the type \"$INSTALLED_TYPE\"" | ||||
echo " but the new version has the type \"$TEMPROOT_TYPE\"" | echo " but the new version has the type \"$TEMPROOT_TYPE\"" | ||||
echo '' | echo '' | ||||
echo " How would you like to handle this?" | echo " How would you like to handle this?" | ||||
echo '' | echo '' | ||||
echo " Use 'r' to remove ${DESTDIR}${COMPFILE#.}" | echo " Use 'r' to remove ${DESTDIR}${COMPFILE#.}" | ||||
case "$TEMPROOT_TYPE" in | case "$TEMPROOT_TYPE" in | ||||
'symbolic link') | 'symbolic link') | ||||
Show All 12 Lines | echo " and create a link to $TARGET in its place" ;; | ||||
mv ${DESTDIR}${COMPFILE#.} ${PRESERVE_FILES_DIR}/ || exit 1 ;; | mv ${DESTDIR}${COMPFILE#.} ${PRESERVE_FILES_DIR}/ || exit 1 ;; | ||||
*) rm -rf ${DESTDIR}${COMPFILE#.} ;; | *) rm -rf ${DESTDIR}${COMPFILE#.} ;; | ||||
esac | esac | ||||
case "$TEMPROOT_TYPE" in | case "$TEMPROOT_TYPE" in | ||||
'symbolic link') ln -sf $TARGET ${DESTDIR}${COMPFILE#.} ;; | 'symbolic link') ln -sf $TARGET ${DESTDIR}${COMPFILE#.} ;; | ||||
esac ;; | esac ;; | ||||
*) echo '' | *) echo '' | ||||
echo "*** See the man page about adding ${COMPFILE#.} to the list of IGNORE_FILES" | echo "*** See the man page about adding ${COMPFILE#.} to the list of IGNORE_FILES" | ||||
echo "*** or ALLOW_SYMLINK" | |||||
press_to_continue ;; | press_to_continue ;; | ||||
esac | esac | ||||
echo '' | echo '' | ||||
fi | fi | ||||
done | done | ||||
for COMPFILE in `find . -type f | sort`; do | for COMPFILE in `find . -type f | sort`; do | ||||
▲ Show 20 Lines • Show All 342 Lines • Show Last 20 Lines |
The quoting is correct here, but there should be an error check. Otherwise, a non-existent DESTDIR will cause mergemaster to install to /.