summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPanu Matilainen <pmatilai@redhat.com>2007-08-09 19:26:05 +0300
committerPanu Matilainen <pmatilai@redhat.com>2007-08-09 19:26:05 +0300
commita77f9d2cd1b4a414632f72cb21297487c45eea31 (patch)
tree2276054b72b5a0af79f4eacb0715387611641437
parent03a0e17d744c84ec7dd424cac72b4257159c2d6f (diff)
parentebfbc82bb1cd01bb58c5263e2bb5cba478667be2 (diff)
downloadlibrpm-tizen-a77f9d2cd1b4a414632f72cb21297487c45eea31.tar.gz
librpm-tizen-a77f9d2cd1b4a414632f72cb21297487c45eea31.tar.bz2
librpm-tizen-a77f9d2cd1b4a414632f72cb21297487c45eea31.zip
Avoid unnecessary .rpmnew and .rpmsave files (rhbz#128622)
Don't create .rpmnew and .rpmsave files when file/symlink on disk differs just by timestamp. Patch by Tomas Mraz.
-rw-r--r--lib/rpmfi.c44
-rw-r--r--lib/rpmfi.h8
-rw-r--r--lib/transaction.c6
3 files changed, 55 insertions, 3 deletions
diff --git a/lib/rpmfi.c b/lib/rpmfi.c
index 64d660dd7..bed84893d 100644
--- a/lib/rpmfi.c
+++ b/lib/rpmfi.c
@@ -22,6 +22,7 @@
#include "rpmte.h"
#include "rpmts.h"
+#include "legacy.h" /* XXX domd5 */
#include "misc.h" /* XXX stripTrailingChar */
#include "rpmmacro.h" /* XXX rpmCleanPath */
#include "legacy.h"
@@ -628,6 +629,49 @@ fileAction rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing)
}
/*@=boundsread@*/
+/*@-boundsread@*/
+int rpmfiConfigConflict(const rpmfi fi)
+{
+ const char * fn = rpmfiFN(fi);
+ int flags = rpmfiFFlags(fi);
+ char buffer[1024];
+ fileTypes newWhat, diskWhat;
+ struct stat sb;
+
+ if (!(flags & RPMFILE_CONFIG) || lstat(fn, &sb)) {
+ return 0;
+ }
+
+ diskWhat = whatis((int_16)sb.st_mode);
+ newWhat = whatis(rpmfiFMode(fi));
+
+ if (newWhat != LINK && newWhat != REG)
+ return 1;
+
+ if (diskWhat != newWhat)
+ return 1;
+
+ memset(buffer, 0, sizeof(buffer));
+ if (newWhat == REG) {
+ const unsigned char * nmd5;
+ if (domd5(fn, (unsigned char *)buffer, 0, NULL))
+ return 0; /* assume file has been removed */
+ nmd5 = rpmfiMD5(fi);
+ if (nmd5 && !memcmp(nmd5, buffer, 16))
+ return 0; /* unmodified config file */
+ } else /* newWhat == LINK */ {
+ const char * nFLink;
+ if (readlink(fn, buffer, sizeof(buffer) - 1) == -1)
+ return 0; /* assume file has been removed */
+ nFLink = rpmfiFLink(fi);
+ if (nFLink && !strcmp(nFLink, buffer))
+ return 0; /* unmodified config file */
+ }
+
+ return 1;
+}
+/*@=boundsread@*/
+
/*@observer@*/
const char * rpmfiTypeString(rpmfi fi)
{
diff --git a/lib/rpmfi.h b/lib/rpmfi.h
index 83810e6be..2e28afece 100644
--- a/lib/rpmfi.h
+++ b/lib/rpmfi.h
@@ -620,6 +620,14 @@ fileAction rpmfiDecideFate(const rpmfi ofi, rpmfi nfi, int skipMissing)
/*@modifies nfi, fileSystem, internalState @*/;
/**
+ * Return whether file is conflicting config
+ * @param fi file info
+ * @return 1 if config file and file on disk conflicts
+ */
+int rpmfiConfigConflict(const rpmfi fi)
+ /*@*/;
+
+/**
* Return formatted string representation of package disposition.
* @param fi file info set
* @return formatted string
diff --git a/lib/transaction.c b/lib/transaction.c
index f541f7eda..cbdecf61d 100644
--- a/lib/transaction.c
+++ b/lib/transaction.c
@@ -547,7 +547,7 @@ static void handleOverlappedFiles(const rpmts ts,
/*@-boundswrite@*/
switch (rpmteType(p)) {
case TR_ADDED:
- { struct stat sb;
+ {
int reportConflicts =
!(rpmtsFilterFlags(ts) & RPMPROB_FILTER_REPLACENEWFILES);
int done = 0;
@@ -556,7 +556,7 @@ static void handleOverlappedFiles(const rpmts ts,
/* XXX is this test still necessary? */
if (fi->actions[i] != FA_UNKNOWN)
/*@switchbreak@*/ break;
- if ((FFlags & RPMFILE_CONFIG) && !lstat(fn, &sb)) {
+ if (rpmfiConfigConflict(fi)) {
/* Here is a non-overlapped pre-existing config file. */
fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
? FA_ALTNAME : FA_BACKUP;
@@ -613,7 +613,7 @@ assert(otherFi != NULL);
/* Try to get the disk accounting correct even if a conflict. */
fixupSize = rpmfiFSize(otherFi);
- if ((FFlags & RPMFILE_CONFIG) && !lstat(fn, &sb)) {
+ if (rpmfiConfigConflict(fi)) {
/* Here is an overlapped pre-existing config file. */
fi->actions[i] = (FFlags & RPMFILE_NOREPLACE)
? FA_ALTNAME : FA_SKIP;