unpack: keep conf_files replaced with symlinks, unpack as .new-pkgver

This commit is contained in:
Duncaen 2019-03-19 13:12:08 +01:00
parent 2ad2659d4c
commit ea2cb1d369
4 changed files with 89 additions and 17 deletions

View File

@ -115,7 +115,7 @@ int HIDDEN xbps_cb_message(struct xbps_handle *, xbps_dictionary_t, const char *
int HIDDEN xbps_entry_is_a_conf_file(xbps_dictionary_t, const char *);
int HIDDEN xbps_entry_install_conf_file(struct xbps_handle *, xbps_dictionary_t,
xbps_dictionary_t, struct archive_entry *, const char *,
const char *);
const char *, bool);
int HIDDEN xbps_repository_find_deps(struct xbps_handle *, xbps_array_t,
xbps_dictionary_t);
xbps_dictionary_t HIDDEN xbps_find_virtualpkg_in_conf(struct xbps_handle *,

View File

@ -63,7 +63,8 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
xbps_dictionary_t pkg_filesd,
struct archive_entry *entry,
const char *entry_pname,
const char *pkgver)
const char *pkgver,
bool symlink)
{
xbps_object_t obj, obj2;
xbps_object_iterator_t iter, iter2;
@ -87,9 +88,10 @@ xbps_entry_install_conf_file(struct xbps_handle *xhp,
xbps_dbg_printf(xhp, "%s: processing conf_file %s\n",
pkgver, entry_pname);
if (pkg_filesd == NULL) {
if (pkg_filesd == NULL || symlink) {
/*
* File exists on disk but it's not managed by the same package.
* 1. File exists on disk but it's not managed by the same package.
* 2. File exists on disk as symlink.
* Install it as file.new-<version>.
*/
version = xbps_pkg_version(pkgver);

View File

@ -87,7 +87,7 @@ unpack_archive(struct xbps_handle *xhp,
const char *file, *entry_pname, *transact, *binpkg_pkgver;
char *pkgname, *buf;
int ar_rv, rv, error, entry_type, flags;
bool preserve, update, file_exists;
bool preserve, update, file_exists, keep_conf_file;
bool skip_extract, force, xucd_stats;
uid_t euid;
@ -287,7 +287,7 @@ unpack_archive(struct xbps_handle *xhp,
* doesn't match, in that case overwrite the file.
* Otherwise skip extracting it.
*/
skip_extract = file_exists = false;
skip_extract = file_exists = keep_conf_file = false;
if (lstat(entry_pname, &st) == 0)
file_exists = true;
/*
@ -303,32 +303,41 @@ unpack_archive(struct xbps_handle *xhp,
"it's preserved.\n", pkgver, entry_pname);
continue;
}
/*
* Check if current entry is a configuration file,
* that should be kept.
*/
if (!force && (entry_type == AE_IFREG)) {
buf = strchr(entry_pname, '.') + 1;
assert(buf != NULL);
keep_conf_file = xbps_entry_is_a_conf_file(binpkg_filesd, buf);
}
/*
* If file to be extracted does not match the file type of
* file currently stored on disk, remove file on disk.
* file currently stored on disk and is not a conf file
* that should be kept, remove file on disk.
*/
if (file_exists &&
if (file_exists && !keep_conf_file &&
((entry_statp->st_mode & S_IFMT) != (st.st_mode & S_IFMT)))
(void)remove(entry_pname);
if (!force && (entry_type == AE_IFREG)) {
buf = strchr(entry_pname, '.') + 1;
assert(buf != NULL);
if (file_exists && S_ISREG(st.st_mode)) {
if (file_exists && (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) {
/*
* Handle configuration files. Check if current
* entry is a configuration file and take action
* if required. Skip packages that don't have
* "conf_files" array on its XBPS_PKGPROPS
* Handle configuration files.
* Skip packages that don't have "conf_files"
* array on its XBPS_PKGPROPS
* dictionary.
*/
if (xbps_entry_is_a_conf_file(binpkg_filesd, buf)) {
if (keep_conf_file) {
if (xhp->unpack_cb != NULL)
xucd.entry_is_conf = true;
rv = xbps_entry_install_conf_file(xhp,
binpkg_filesd, pkg_filesd, entry,
entry_pname, pkgver);
entry_pname, pkgver, S_ISLNK(st.st_mode));
if (rv == -1) {
/* error */
goto out;

View File

@ -165,9 +165,70 @@ tc4_body() {
atf_check_equal $rval 0
}
# 5th test: configuration file replaced with symlink on disk, modified on upgrade.
# result: install new file as "<conf_file>.new-<version>".
atf_test_case tc5
tc5_head() {
atf_set "descr" "Tests for configuration file handling: on-disk replaced with symlink, upgrade modified"
}
tc5_body() {
mkdir repo
cd repo
mkdir pkg_a
echo "fooblah" > pkg_a/cf1.conf
chmod 644 pkg_a/cf1.conf
xbps-create -A noarch -n a-0.1_1 -s "pkg a" --config-files "/cf1.conf" pkg_a
atf_check_equal $? 0
rm -rf pkg_a
xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0
xbps-install -C null.conf -r rootdir --repository=$PWD -yvd a
atf_check_equal $? 0
mv rootdir/cf1.conf rootdir/foobar.conf
ln -sf foobar.conf rootdir/cf1.conf
sed -e 's,fooblah,blahfoo,' -i rootdir/foobar.conf
chmod 644 rootdir/foobar.conf
mkdir pkg_a
echo "bazbar" > pkg_a/cf1.conf
chmod 644 pkg_a/cf1.conf
xbps-create -A noarch -n a-0.2_1 -s "pkg a" --config-files "/cf1.conf" pkg_a
atf_check_equal $? 0
xbps-rindex -d -a $PWD/*.xbps
atf_check_equal $? 0
rm -rf pkg_a
xbps-install -C null.conf -r rootdir --repository=$PWD -yuvd
atf_check_equal $? 0
ls -lsa rootdir
test -h rootdir/cf1.conf
atf_check_equal $? 0
result="$(cat rootdir/cf1.conf)"
rval=1
if [ "${result}" = "blahfoo" ]; then
rval=0
fi
echo "result: ${result}"
echo "expected: blahfoo"
atf_check_equal $rval 0
rval=1
if [ -s rootdir/cf1.conf.new-0.2_1 ]; then
rval=0
fi
atf_check_equal $rval 0
}
atf_init_test_cases() {
atf_add_test_case tc1
atf_add_test_case tc2
atf_add_test_case tc3
atf_add_test_case tc4
atf_add_test_case tc5
}