diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/rpmfi.c | 136 | ||||
-rw-r--r-- | lib/rpmfi_internal.h | 25 | ||||
-rw-r--r-- | lib/rpmfiles.h | 2 | ||||
-rw-r--r-- | lib/transaction.c | 15 |
4 files changed, 177 insertions, 1 deletions
diff --git a/lib/rpmfi.c b/lib/rpmfi.c index 320296a4d..93970ea05 100644 --- a/lib/rpmfi.c +++ b/lib/rpmfi.c @@ -1089,6 +1089,142 @@ exit: return action; } + +rpmFileAction rpmfilesSetMutableAction(rpmfiles ofi, int oix, + rpmfiles nfi, int nix) +{ + char * fn = rpmfilesFN(nfi, nix); + rpmFileTypes diskWhat; + struct stat sb; + int action = FA_UNKNOWN; + + /* The file doesn't exist on the disk. Create it. */ + if (lstat(fn, &sb)) { + action = FA_CREATE; + goto exit; + } + + diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode); + + if ((diskWhat == REG) && + (rpmfiWhatis(rpmfilesFMode(ofi, oix)) == REG) && + (rpmfiWhatis(rpmfilesFMode(nfi, nix)) == REG) ) { + char buffer[1024]; + int oalgo, nalgo; + size_t odiglen, ndiglen; + const unsigned char * odigest, * ndigest; + const char * nfuser, * ofuser; + uid_t uid; + const char * nfgroup, * ofgroup; + gid_t gid; + + /* If the file on disk is identical to the one in new pkg, then touch it */ + if (rpmfilesFSize(nfi, nix) == sb.st_size) { + + if (rpmfilesFMode(nfi, nix) == ((rpm_mode_t)sb.st_mode)) { + + nfuser = rpmfilesFUser(nfi, nix); + if ((nfuser && rpmugUid(nfuser, &uid) == 0) && + (uid == sb.st_uid)) { + + nfgroup = rpmfilesFGroup(nfi, nix); + if ((nfgroup && rpmugGid(nfgroup, &gid) == 0) && + (gid == sb.st_gid)) { + + ndigest = rpmfilesFDigest(nfi, nix, &nalgo, &ndiglen); + if ((!rpmDoDigest(nalgo, fn, 0, (unsigned char *)buffer, NULL)) && + (ndigest && memcmp(ndigest, buffer, ndiglen) == 0)) { + action = FA_TOUCH; + goto exit; + } + } + } + } + } + + /* If the file on disk is identical to the one in old pkg, then create it */ + if (rpmfilesFSize(ofi, oix) == sb.st_size) { + + if (rpmfilesFMode(ofi, oix) == ((rpm_mode_t)sb.st_mode)) { + + ofuser = rpmfilesFUser(ofi, oix); + if ((ofuser && rpmugUid(ofuser, &uid) == 0) && + (uid == sb.st_uid)) { + + ofgroup = rpmfilesFGroup(ofi, oix); + if ((ofgroup && rpmugGid(ofgroup, &gid) == 0) && + (gid == sb.st_gid)) { + + odigest = rpmfilesFDigest(ofi, oix, &oalgo, &odiglen); + if ((!rpmDoDigest(oalgo, fn, 0, (unsigned char *)buffer, NULL)) && + (odigest && memcmp(odigest, buffer, odiglen) == 0)) { + action = FA_CREATE; + goto exit; + } + } + } + } + } + + /* file is changed, let it be */ + action = FA_SKIP; + + } else if ((diskWhat == LINK) && + (rpmfiWhatis(rpmfilesFMode(ofi, oix)) == LINK) && + (rpmfiWhatis(rpmfilesFMode(nfi, nix)) == LINK) ) { + + char buffer[1024]; + const char * oFLink, * nFLink; + + /* if the link on disk is identical to the one in new pkg, then touch it */ + nFLink = rpmfilesFLink(nfi, nix); + + ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1); + if (link_len != -1) { + buffer[link_len] = '\0'; + if (nFLink && rstreq(nFLink, buffer)) { + action = FA_TOUCH; + goto exit; + } + } + + /* if the link on disk is identical to the one in old pkg, then create it */ + oFLink = rpmfilesFLink(ofi, oix); + if ((link_len != -1) && (oFLink && rstreq(oFLink, buffer))) { + action = FA_CREATE; + goto exit; + } + + /* link is changed, let it be */ + action = FA_SKIP; + } + +exit: + free(fn); + return action; + } + + +rpmFileAction rpmfilesSetNoupdateAction(rpmfiles ofi, int oix, + rpmfiles nfi, int nix) +{ + char * fn = rpmfilesFN(nfi, nix); + struct stat sb; + int action = FA_UNKNOWN; + + if (lstat(fn, &sb)) { + /* The file/link/ doesn't exist on the disk. Create it. */ + action = FA_CREATE; + } else { + /* The file exists, let it be. */ + action = FA_SKIP; + } + + free(fn); + return action; + } + + int rpmfilesConfigConflict(rpmfiles fi, int ix) { char * fn = NULL; diff --git a/lib/rpmfi_internal.h b/lib/rpmfi_internal.h index cb3284c0f..804333f2d 100644 --- a/lib/rpmfi_internal.h +++ b/lib/rpmfi_internal.h @@ -73,6 +73,31 @@ rpmFileAction rpmfilesDecideFate(rpmfiles ofi, int oix, rpmfiles nfi, int nix, int skipMissing); + +/** \ingroup rpmfi + * Return action which should be done with the %mutable file + * @param new file info set + * @param new file index + * @param old file info set + * @param old file index + * @return action name + */ +RPM_GNUC_INTERNAL +rpmFileAction rpmfilesSetMutableAction(rpmfiles ofi, int oix, + rpmfiles nfi, int nix); + +/** \ingroup rpmfi + * Return action which should be done with the %noupdate file + * @param new file info set + * @param new file index + * @param old file info set + * @param old file index + * @return action name + */ +RPM_GNUC_INTERNAL +rpmFileAction rpmfilesSetNoupdateAction(rpmfiles ofi, int oix, + rpmfiles nfi, int nix); + RPM_GNUC_INTERNAL int rpmfilesConfigConflict(rpmfiles fi, int ix); diff --git a/lib/rpmfiles.h b/lib/rpmfiles.h index 4dba88fc4..8e92d0c4f 100644 --- a/lib/rpmfiles.h +++ b/lib/rpmfiles.h @@ -60,6 +60,8 @@ enum rpmfileAttrs_e { RPMFILE_README = (1 << 8), /*!< from %%readme */ /* bits 9-10 unused */ RPMFILE_PUBKEY = (1 << 11), /*!< from %%pubkey */ + RPMFILE_MUTABLE = (1 << 12), /*!< from %%mutable or %updatepolicy(mutable) */ + RPMFILE_NOUPDATE = (1 << 13), /*!< from %%noupdate or %updatepolicy(noupdate) */ }; typedef rpmFlags rpmfileAttrs; diff --git a/lib/transaction.c b/lib/transaction.c index d8cd1e6e9..e7efe65c2 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -414,6 +414,7 @@ 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); + rpmFileAction action; if (XFA_SKIPPING(rpmfsGetAction(fs, fx))) return; @@ -471,10 +472,22 @@ static void handleInstInstalledFile(const rpmts ts, rpmte p, rpmfiles fi, int fx /* Determine config file disposition, skipping missing files (if any). */ if (isCfgFile) { int skipMissing = ((rpmtsFlags(ts) & RPMTRANS_FLAG_ALLFILES) ? 0 : 1); - rpmFileAction action; action = rpmfilesDecideFate(otherFi, ofx, fi, fx, skipMissing); rpmfsSetAction(fs, fx, action); + + } else { + if (rpmfilesFFlags(fi, fx) & RPMFILE_MUTABLE) { + action = rpmfilesSetMutableAction(otherFi, ofx, fi, fx); + rpmfsSetAction(fs, fx, action); + + } else { + if (rpmfilesFFlags(fi, fx) & RPMFILE_NOUPDATE) { + action = rpmfilesSetNoupdateAction(otherFi, ofx, fi, fx); + rpmfsSetAction(fs, fx, action); + } + } } + rpmfilesSetFReplacedSize(fi, fx, rpmfilesFSize(otherFi, ofx)); } |