changeset: 6235:0d4b8cfd8dc9 tag: tip user: Panu Matilainen date: Thu Aug 09 15:15:24 2007 +0300 files: lib/rpmfi.c lib/rpmfi.h lib/transaction.c description: 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. diff -r debbc872bbb3 -r 0d4b8cfd8dc9 lib/rpmfi.c --- a/lib/rpmfi.c Thu Aug 09 14:18:11 2007 +0300 +++ b/lib/rpmfi.c Thu Aug 09 15:15:24 2007 +0300 @@ -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" @@ -625,6 +626,49 @@ fileAction rpmfiDecideFate(const rpmfi o * merge the difference ala CVS, but... */ return save; +} +/*@=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@*/ diff -r debbc872bbb3 -r 0d4b8cfd8dc9 lib/rpmfi.h --- a/lib/rpmfi.h Thu Aug 09 14:18:11 2007 +0300 +++ b/lib/rpmfi.h Thu Aug 09 15:15:24 2007 +0300 @@ -620,6 +620,14 @@ fileAction rpmfiDecideFate(const rpmfi o /*@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 -r debbc872bbb3 -r 0d4b8cfd8dc9 lib/transaction.c --- a/lib/transaction.c Thu Aug 09 14:18:11 2007 +0300 +++ b/lib/transaction.c Thu Aug 09 15:15:24 2007 +0300 @@ -547,7 +547,7 @@ static void handleOverlappedFiles(const /*@-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 /* 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;