Radish alpha
H
rad:z3QDZAW2FAfuLvihrhiyDC9fAD8G9
HardenedBSD Package Manager
Radicle
Git
pkg_add: remove existing file before renaming temp directory
Baptiste Daroussin committed 1 month ago
commit bc7e4441d7ddee6e1e5f4c74b50db15bc68a83ad
parent 33ce293
2 files changed +42 -0
modified libpkg/pkg_add.c
@@ -990,6 +990,10 @@ pkg_extract_finalize(struct pkg *pkg, tempdirs_t *tempdirs)
	if (tempdirs != NULL) {
		vec_foreach(*tempdirs, i) {
			struct tempdir *t = tempdirs->d[i];
+
			if (fstatat(pkg->rootfd, RELATIVE_PATH(t->name),
+
			    &st, AT_SYMLINK_NOFOLLOW) == 0)
+
				unlinkat(pkg->rootfd,
+
				    RELATIVE_PATH(t->name), 0);
			if (renameat(pkg->rootfd, RELATIVE_PATH(t->temp),
			    pkg->rootfd, RELATIVE_PATH(t->name)) != 0) {
				pkg_fatal_errno("Failed to rename %s -> %s",
modified tests/frontend/upgrade.sh
@@ -19,6 +19,7 @@ tests_init \
	upgrade_glob_abi_arch \
	upgrade_autoremove \
	upgrade_autoremove_flag \
+
	symlink_to_dir_upgrade \

issue1881_body() {
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg pkg1 pkg_a 1
@@ -731,3 +732,40 @@ EOF
	atf_check -s exit:0 pkg info -e master
	atf_check -s exit:1 pkg info -e olddep
}
+

+
symlink_to_dir_upgrade_body() {
+
	# PR #2041: when v1 has a symlink and v2 replaces it with a real
+
	# directory containing files, pkg should remove the symlink before
+
	# renaming the temporary directory into place.
+

+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg "pkg" "pkg" "1"
+
	mkdir -p base
+
	echo "content" > base/file
+
	ln -s ../base errors-mx
+
	echo "${TMPDIR}/base/file" > plist-1
+
	echo "${TMPDIR}/errors-mx" >> plist-1
+
	atf_check pkg create -M pkg.ucl -p plist-1
+
	mkdir target
+
	atf_check -o ignore pkg -o REPOS_DIR="${TMPDIR}" -r ${TMPDIR}/target install -Uy ${TMPDIR}/pkg-1.pkg
+

+
	# Verify symlink was installed
+
	atf_check test -L target/${TMPDIR}/errors-mx
+

+
	# v2: replaces symlink with a real directory containing a file
+
	atf_check -s exit:0 sh ${RESOURCEDIR}/test_subr.sh new_pkg "pkg" "pkg" "2"
+
	rm errors-mx
+
	mkdir errors-mx
+
	echo "new content" > errors-mx/newfile
+
	echo "${TMPDIR}/errors-mx/newfile" > plist-2
+
	atf_check pkg create -M pkg.ucl -p plist-2
+

+
	# Upgrade: should succeed despite symlink existing at target
+
	atf_check \
+
		-o ignore \
+
		-s exit:0 \
+
		pkg -o REPOS_DIR="${TMPDIR}" -r ${TMPDIR}/target install -Uy ${TMPDIR}/pkg-2.pkg
+

+
	# Verify the directory replaced the symlink
+
	atf_check test -d target/${TMPDIR}/errors-mx
+
	atf_check test -f target/${TMPDIR}/errors-mx/newfile
+
}