Detect attempts to replace directory symlink to directory in package

- Rpm cannot currently *correctly* deal with directory symlink changing
  to a directory through updates, detect early and abort with conflicts
  instead of proceeding with known-broken results: previously these
  would seemingly succeed but without actually doing the requested
  changes, and leaving orphans on the disk. Far less evil than the
  directory replacement failure but incorrect anyway.
- Same %pretrans wackiness as with directory replacements applies here.
- Adjust test-suite to match the new behavior.
- It's possible there are packages that have been relying on the former
  broken "success" results, so this might need further fine-tuning...
This commit is contained in:
Panu Matilainen 2012-08-24 13:36:52 +03:00
parent 00d82f1322
commit a7a06ec88f
3 changed files with 18 additions and 11 deletions

View File

@ -287,11 +287,19 @@ static int handleRemovalConflict(rpmfi fi, int fx, rpmfi ofi, int ofx)
rpmFileTypes ft = rpmfiWhatis(rpmfiFModeIndex(fi, fx));
rpmFileTypes oft = rpmfiWhatis(rpmfiFModeIndex(ofi, ofx));
struct stat sb;
char *fn = NULL;
if (oft == XDIR) {
/* We can't handle directory changing to anything else */
if (ft != XDIR)
rConflicts = 1;
} else if (oft == LINK) {
/* We can't correctly handle directory symlink changing to directory */
if (ft == XDIR) {
fn = rpmfiFNIndex(fi, fx);
if (stat(fn, &sb) == 0 && S_ISDIR(sb.st_mode))
rConflicts = 1;
}
}
/*
@ -299,12 +307,13 @@ static int handleRemovalConflict(rpmfi fi, int fx, rpmfi ofi, int ofx)
* already been changed to the new type, we should be ok afterall.
*/
if (rConflicts) {
char *fn = rpmfiFNIndex(fi, fx);
if (fn == NULL)
fn = rpmfiFNIndex(fi, fx);
if (lstat(fn, &sb) || rpmfiWhatis(sb.st_mode) == ft)
rConflicts = 0;
free(fn);
}
free(fn);
return rConflicts;
}

View File

@ -259,9 +259,7 @@ runroot rpm -U "${TOPDIR}"/RPMS/noarch/symlinktest-1.0-2.noarch.rpm
AT_CLEANUP
# ------------------------------
# Replace symlink with a directory - the upgrade succeeds but leaves an
# orphan directory that the symlink now points to. Should verify the
# result more carefully...
# Replace symlink with a directory
AT_SETUP([rpm -U replacing symlink with directory])
AT_KEYWORDS([install])
AT_CHECK([
@ -278,7 +276,8 @@ runroot rpmbuild --quiet -bb \
runroot rpm -U "${TOPDIR}"/RPMS/noarch/symlinktest-1.0-1.noarch.rpm
runroot rpm -U "${TOPDIR}"/RPMS/noarch/symlinktest-1.0-2.noarch.rpm
],
[0],
[2],
[],
[])
[ file /usr/share/symlinktest from install of symlinktest-1.0-2.noarch conflicts with file from package symlinktest-1.0-1.noarch
])
AT_CLEANUP

View File

@ -301,7 +301,6 @@ test -d "${tf}"
[])
AT_CLEANUP
# XXX: this "succeeds" but with bogus results
AT_SETUP([upgrade directory link to directory])
AT_KEYWORDS([install])
AT_CHECK([
@ -325,12 +324,12 @@ runroot rpmbuild --quiet -bb \
runroot rpm -U "${TOPDIR}"/RPMS/noarch/replacetest-1.0-1.noarch.rpm
readlink "${tf}"
runroot rpm -U "${TOPDIR}"/RPMS/noarch/replacetest-2.0-1.noarch.rpm
test -d "${tf}"
],
[0],
[2],
[zoo
],
[])
[ file /opt/foo from install of replacetest-2.0-1.noarch conflicts with file from package replacetest-1.0-1.noarch
])
AT_CLEANUP
AT_SETUP([upgrade empty directory to empty directory])