--- lib/rpmfiles.h.orig +++ lib/rpmfiles.h @@ -156,7 +156,7 @@ typedef rpmFlags rpmfiFlags; #define RPMFI_FLAGS_ERASE \ (RPMFI_NOFILECLASS | RPMFI_NOFILELANGS | \ - RPMFI_NOFILEMTIMES | RPMFI_NOFILERDEVS | RPMFI_NOFILEINODES | \ + RPMFI_NOFILEMTIMES | RPMFI_NOFILERDEVS | \ RPMFI_NOFILEVERIFYFLAGS) #define RPMFI_FLAGS_INSTALL \ --- lib/transaction.c.orig +++ lib/transaction.c @@ -231,11 +231,11 @@ static void rpmtsUpdateDSI(const rpmts ts, dev_t dev, const char *dirName, dsi->bneeded += bneeded; dsi->ineeded++; if (prevSize) { - dsi->bdelta += BLOCK_ROUND(prevSize, dsi->bsize); + dsi->bdelta += BLOCK_ROUND(prevSize - 1, dsi->bsize); dsi->idelta++; } if (fixupSize) { - dsi->bdelta += BLOCK_ROUND(fixupSize, dsi->bsize); + dsi->bdelta += BLOCK_ROUND(fixupSize - 1, dsi->bsize); dsi->idelta++; } @@ -412,6 +412,9 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx { rpmfs fs = rpmteGetFileStates(p); int isCfgFile = ((rpmfilesFFlags(otherFi, ofx) | rpmfilesFFlags(fi, fx)) & RPMFILE_CONFIG); + rpm_loff_t otherFileSize; + int nlink; + const int *links; if (XFA_SKIPPING(rpmfsGetAction(fs, fx))) return; @@ -481,7 +484,15 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx } } - rpmfilesSetFReplacedSize(fi, fx, rpmfilesFSize(otherFi, ofx)); + otherFileSize = rpmfilesFSize(otherFi, ofx); + + /* Only account for the last file of a hardlink set */ + nlink = rpmfilesFLinks(otherFi, ofx, &links); + if (nlink > 1 && links[nlink - 1] != ofx) + otherFileSize = 0; + + /* Add one to make sure the size is not zero */ + rpmfilesSetFReplacedSize(fi, fx, otherFileSize + 1); } /** @@ -491,6 +502,7 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx static void handleOverlappedFiles(rpmts ts, fingerPrintCache fpc, rpmte p, rpmfiles fi) { rpm_loff_t fixupSize = 0; + rpm_loff_t fileSize = 0; int i, j; rpmfs fs = rpmteGetFileStates(p); rpmfs otherFs; @@ -628,7 +640,8 @@ assert(otherFi != NULL); break; /* Try to get the disk accounting correct even if a conflict. */ - fixupSize = rpmfilesFSize(otherFi, otherFileNum); + /* Add one to make sure the size is not zero */ + fixupSize = rpmfilesFSize(otherFi, otherFileNum) + 1; if (rpmfilesConfigConflict(fi, i)) { /* Here is an overlapped pre-existing config file. */ @@ -675,9 +688,16 @@ assert(otherFi != NULL); } rpmfilesFree(otherFi); + fileSize = rpmfilesFSize(fi, i); + nlink = rpmfilesFLinks(fi, i, &links); + if (nlink > 1 && links[nlink - 1] != i) { + /* Only account for the last file of a hardlink set */ + fileSize = 0; + fixupSize = fixupSize ? 1 : 0; + } /* Update disk space info for a file. */ rpmtsUpdateDSI(ts, fpEntryDev(fpc, fiFps), fpEntryDir(fpc, fiFps), - rpmfilesFSize(fi, i), rpmfilesFReplacedSize(fi, i), + fileSize, rpmfilesFReplacedSize(fi, i), fixupSize, rpmfsGetAction(fs, i)); }