git: c0f52443166a - main - freebsd-update: handle directories changing to files

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Wed, 18 Oct 2023 14:54:00 UTC
The branch main has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=c0f52443166ae7ecd512ab0350469d9c3648788c

commit c0f52443166ae7ecd512ab0350469d9c3648788c
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2023-09-12 02:59:30 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2023-10-18 14:48:58 +0000

    freebsd-update: handle directories changing to files
    
    Further to f6d37c9ca13f ("freebsd-update: handle file -> directory on
    upgrade"), handle the reverse case of a directory changing to a file.
    We may not encounter this case on upgradess (before freebsd-update is
    retired) but it is needed to support rollback.
    
    PR:             273950
    Reviewed by:    dim
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D41945
---
 usr.sbin/freebsd-update/freebsd-update.sh | 19 +++++++++++++++++--
 1 file changed, 17 insertions(+), 2 deletions(-)

diff --git a/usr.sbin/freebsd-update/freebsd-update.sh b/usr.sbin/freebsd-update/freebsd-update.sh
index 438e13a51154..30e78f9bffa2 100644
--- a/usr.sbin/freebsd-update/freebsd-update.sh
+++ b/usr.sbin/freebsd-update/freebsd-update.sh
@@ -2894,6 +2894,15 @@ backup_kernel () {
 	set +f
 }
 
+# Check for and remove an existing directory that conflicts with the file or
+# symlink that we are going to install.
+dir_conflict () {
+	if [ -d "$1" ]; then
+		echo "Removing conflicting directory $1"
+		rm -rf -- "$1"
+	fi
+}
+
 # Install new files
 install_from_index () {
 	# First pass: Do everything apart from setting file flags.  We
@@ -2914,6 +2923,7 @@ install_from_index () {
 			    -m ${PERM} ${BASEDIR}/${FPATH}
 			;;
 		f)
+			dir_conflict "${BASEDIR}/${FPATH}"
 			if [ -z "${LINK}" ]; then
 				# Create a file, without setting flags.
 				gunzip < files/${HASH}.gz > ${HASH}
@@ -2926,6 +2936,7 @@ install_from_index () {
 			fi
 			;;
 		L)
+			dir_conflict "${BASEDIR}/${FPATH}"
 			# Create a symlink
 			ln -sfh ${HASH} ${BASEDIR}/${FPATH}
 			;;
@@ -2962,10 +2973,14 @@ install_delete () {
 			rmdir ${BASEDIR}/${FPATH}
 			;;
 		f)
-			rm ${BASEDIR}/${FPATH}
+			if [ -f "${BASEDIR}/${FPATH}" ]; then
+				rm "${BASEDIR}/${FPATH}"
+			fi
 			;;
 		L)
-			rm ${BASEDIR}/${FPATH}
+			if [ -L "${BASEDIR}/${FPATH}" ]; then
+				rm "${BASEDIR}/${FPATH}"
+			fi
 			;;
 		esac
 	done < killfiles