File patchrpms.diff of Package rpm.SLE_11
Add support for patch rpms. Maybe not needed that much any more,
as delta rpms are more efficient and do not need so much evil
rpm patchery.
rh#103205
Index: lib/depends.c
===================================================================
--- lib/depends.c.orig
+++ lib/depends.c
@@ -159,6 +159,7 @@ int rpmtsAddInstallElement(rpmts ts, Hea
const char * os;
rpmds oldChk, newChk;
rpmds obsoletes;
+ rpmds patches;
alKey pkgKey; /* addedPackages key */
int xx;
int ec = 0;
@@ -399,6 +400,40 @@ addheader:
}
obsoletes = rpmdsFree(obsoletes);
+ patches = rpmdsLink(rpmteDS(p, RPMTAG_PATCHESNAME), "Patches");
+ patches = rpmdsInit(patches);
+ if (patches != NULL)
+ while (rpmdsNext(patches) >= 0) {
+ const char * Name;
+
+ if ((Name = rpmdsN(patches)) == NULL)
+ continue; /* XXX can't happen */
+
+ /* Ignore colored patches not in our rainbow. */
+ dscolor = rpmdsColor(patches);
+ if (tscolor && dscolor && !(tscolor & dscolor))
+ continue;
+
+ mi = rpmtsInitIterator(ts, RPMTAG_NAME, Name, 0);
+
+ xx = rpmdbPruneIterator(mi,
+ ts->removedPackages, ts->numRemovedPackages, 1);
+
+ while((oh = rpmdbNextIterator(mi)) != NULL) {
+ /* Ignore colored packages not in our rainbow. */
+ ohcolor = hGetColor(oh);
+ if (tscolor && hcolor && ohcolor && !(hcolor & ohcolor))
+ /*@innercontinue@*/ continue;
+ if (rpmdsEVR(patches) == NULL
+ || rpmdsNVRMatchesDep(oh, patches, _rpmds_nopromote)) {
+ if (rpmVersionCompare(h, oh))
+ xx = removePackage(ts, oh, rpmdbGetIteratorOffset(mi), pkgKey);
+ }
+ }
+ mi = rpmdbFreeIterator(mi);
+ }
+ patches = rpmdsFree(patches);
+
ec = 0;
exit:
@@ -656,6 +691,57 @@ exit:
return rc;
}
+static int checkPatchDeps(rpmts ts, rpmte p, int reportprobs)
+{
+ const char * Name;
+ Header h;
+ rpmds patches;
+ rpmds this;
+ rpmdbMatchIterator mi;
+
+ patches = rpmdsInit(rpmteDS(p, RPMTAG_PATCHESNAME));
+ if (!patches)
+ return 0;
+ this = rpmteDS(p, RPMTAG_NAME);
+
+ mi = rpmtsInitIterator(ts, RPMTAG_NAME, rpmdsN(this), 0);
+ while ((h = rpmdbNextIterator(mi)) != NULL) {
+ if (rpmdsNVRMatchesDep(h, this, _rpmds_nopromote)) {
+ rpmdsNotify(this, _("(patch refresh)"), 0);
+ p->hPatched = headerLink(h);
+ p->isPatchRefresh = 1;
+ mi = rpmdbFreeIterator(mi);
+ return 0;
+ }
+ }
+ mi = rpmdbFreeIterator(mi);
+
+ while (rpmdsNext(patches) >= 0) {
+ if ((Name = rpmdsN(patches)) == NULL)
+ return 1; /* XXX can't happen */
+ mi = rpmtsInitIterator(ts, RPMTAG_NAME, Name, 0);
+ while ((h = rpmdbNextIterator(mi)) != NULL) {
+ if (rpmdsNVRMatchesDep(h, patches, _rpmds_nopromote)) {
+ rpmdsNotify(patches, _("(db package)"), 0);
+ p->hPatched = headerLink(h);
+ p->isPatchRefresh = 0;
+ mi = rpmdbFreeIterator(mi);
+ return 0;
+ }
+ }
+ mi = rpmdbFreeIterator(mi);
+ }
+
+ rpmdsNotify(patches, NULL, 1);
+ if (reportprobs) {
+ patches = rpmdsInit(patches);
+ rpmdsNext(patches);
+ rpmdsProblem(ts->probs, rpmteNEVR(p), patches, NULL, 1);
+ }
+ return 0;
+}
+
+
/**
* Check added requires/conflicts against against installed+added packages.
* @param ts transaction set
@@ -1730,6 +1816,7 @@ int rpmtsCheck(rpmts ts)
rpmteDS(p, RPMTAG_CONFLICTNAME),
NULL,
tscolor, 1);
+ rc |= checkPatchDeps(ts, p, 1);
if (rc)
goto exit;
@@ -1827,3 +1914,22 @@ exit:
/*@=branchstate@*/
return rc;
}
+
+void rpmtsPatchCheck(rpmts ts)
+{
+ int closeatexit = 0;
+ rpmtsi pi = NULL; rpmte p;
+
+ if (rpmtsGetRdb(ts) == NULL && ts->dbmode != -1) {
+ if ((rpmtsOpenDB(ts, ts->dbmode)) != 0)
+ return;
+ closeatexit = 1;
+ }
+ pi = rpmtsiInit(ts);
+ while ((p = rpmtsiNext(pi, TR_ADDED)) != NULL)
+ if (p->key) /* key is filename for install, zero for verify */
+ (void)checkPatchDeps(ts, p, 0);
+ pi = rpmtsiFree(pi);
+ if (closeatexit)
+ (void)rpmtsCloseDB(ts);
+}
Index: lib/formats.c
===================================================================
--- lib/formats.c.orig
+++ lib/formats.c
@@ -232,6 +232,8 @@ static /*@only@*/ char * fflagsFormat(in
strcat(buf, "l");
if (anint & RPMFILE_README)
strcat(buf, "r");
+ if (anint & RPMFILE_UNPATCHED)
+ strcat(buf, "u");
/*@=boundswrite@*/
val = xmalloc(5 + padding);
Index: lib/fsm.c
===================================================================
--- lib/fsm.c.orig
+++ lib/fsm.c
@@ -707,7 +707,7 @@ assert(rpmteType(fi->te) == TR_ADDED);
break;
case FA_BACKUP:
- if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
+ if (!(fsm->fflags & (RPMFILE_GHOST|RPMFILE_UNPATCHED))) /* XXX Don't if %ghost file. */
switch (rpmteType(fi->te)) {
case TR_ADDED:
fsm->osuffix = SUFFIX_RPMORIG;
@@ -720,13 +720,13 @@ assert(rpmteType(fi->te) == TR_ADDED);
case FA_ALTNAME:
assert(rpmteType(fi->te) == TR_ADDED);
- if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
+ if (!(fsm->fflags & (RPMFILE_GHOST|RPMFILE_UNPATCHED))) /* XXX Don't if %ghost file. */
fsm->nsuffix = SUFFIX_RPMNEW;
break;
case FA_SAVE:
assert(rpmteType(fi->te) == TR_ADDED);
- if (!(fsm->fflags & RPMFILE_GHOST)) /* XXX Don't if %ghost file. */
+ if (!(fsm->fflags & (RPMFILE_GHOST|RPMFILE_UNPATCHED))) /* XXX Don't if %ghost file. */
fsm->osuffix = SUFFIX_RPMSAVE;
break;
case FA_ERASE:
@@ -1740,7 +1740,7 @@ int fsmStage(FSM_t fsm, fileStage stage)
}
if (fsm->goal == FSM_PKGBUILD) {
- if (fsm->fflags & RPMFILE_GHOST) /* XXX Don't if %ghost file. */
+ if (fsm->fflags & (RPMFILE_GHOST|RPMFILE_UNPATCHED)) /* XXX Don't if %ghost file. */
break;
if (!S_ISDIR(st->st_mode) && st->st_nlink > 1) {
struct hardLink_s * li, * prev;
Index: lib/poptQV.c
===================================================================
--- lib/poptQV.c.orig
+++ lib/poptQV.c
@@ -171,6 +171,7 @@ static void queryArgCallback(poptContext
case 'l': qva->qva_flags |= QUERY_FOR_LIST; break;
case 's': qva->qva_flags |= QUERY_FOR_STATE | QUERY_FOR_LIST;
break;
+ case 'P': qva->qva_flags |= QUERY_FOR_PATCHES; break;
case POPT_DUMP: qva->qva_flags |= QUERY_FOR_DUMPFILES | QUERY_FOR_LIST;
break;
@@ -278,6 +279,8 @@ struct poptOption rpmQueryPoptTable[] =
N_("skip %%readme files"), NULL },
#endif
+ { "patches", 'P', 0, 0, 'P',
+ N_("list patches or patched files "), NULL },
{ "qf", '\0', POPT_ARG_STRING | POPT_ARGFLAG_DOC_HIDDEN, 0,
POPT_QUERYFORMAT, NULL, NULL },
{ "queryformat", '\0', POPT_ARG_STRING, 0, POPT_QUERYFORMAT,
Index: lib/query.c
===================================================================
--- lib/query.c.orig
+++ lib/query.c
@@ -258,6 +258,10 @@ int showQueryPackage(QVA_t qva, rpmts ts
te = t + tx;
}
+ /* If querying patches, skip unpatched files. */
+ if ((qva->qva_flags & QUERY_FOR_PATCHES) && (fflags & RPMFILE_UNPATCHED))
+ continue;
+
/*@-boundswrite@*/
if (!rpmIsVerbose() && prefix)
te = stpcpy(te, prefix);
@@ -377,6 +381,21 @@ void rpmDisplayQueryTags(FILE * fp)
}
}
+static int isPatch(Header h)
+{
+ int i, requiresCount = 0;
+ const char ** requires;
+
+ if (!headerGetEntry(h, RPMTAG_REQUIRENAME, NULL, (void **) &requires, &requiresCount))
+ return 0;
+ for (i = 0; i < requiresCount; i++)
+ if (!strcmp("rpmlib(PatchRPMs)", requires[i]))
+ break;
+ if (requiresCount)
+ free(requires);
+ return i < requiresCount;
+}
+
static int rpmgiShowMatches(QVA_t qva, rpmts ts)
/*@globals rpmGlobalMacroContext, h_errno, internalState @*/
/*@modifies qva, rpmGlobalMacroContext, h_errno, internalState @*/
@@ -391,6 +410,8 @@ static int rpmgiShowMatches(QVA_t qva, r
h = rpmgiHeader(gi);
if (h == NULL) /* XXX perhaps stricter break instead? */
continue;
+ if ((qva->qva_flags & QUERY_FOR_PATCHES) != 0 && !isPatch(h))
+ continue;
if ((rc = qva->qva_showPackage(qva, ts, h)) != 0)
ec = rc;
if (qva->qva_source == RPMQV_DBOFFSET)
@@ -406,6 +427,8 @@ int rpmcliShowMatches(QVA_t qva, rpmts t
while ((h = rpmdbNextIterator(qva->qva_mi)) != NULL) {
int rc;
+ if ((qva->qva_flags & QUERY_FOR_PATCHES) != 0 && !isPatch(h))
+ continue;
if ((rc = qva->qva_showPackage(qva, ts, h)) != 0)
ec = rc;
if (qva->qva_source == RPMQV_DBOFFSET)
@@ -703,7 +726,17 @@ int rpmcliArgIter(rpmts ts, QVA_t qva, A
switch (qva->qva_source) {
case RPMQV_ALL:
- qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0);
+ if ((!argv || !*argv) && (qva->qva_flags & QUERY_FOR_PATCHES) != 0) {
+ qva->qva_gi = rpmgiNew(ts, RPMTAG_REQUIRENAME, "rpmlib(PatchRPMs)", 0);
+ qva->qva_gi->mi = rpmtsInitIterator(qva->qva_gi->ts, qva->qva_gi->tag, qva->qva_gi->keyp, qva->qva_gi->keylen);
+ if (qva->qva_gi->mi == NULL) {
+ rpmError(RPMERR_QUERYINFO, _("no patch-rpm installed\n"));
+ break;
+ }
+ qva->qva_gi->mi = rpmdbFreeIterator(qva->qva_gi->mi);
+ } else {
+ qva->qva_gi = rpmgiNew(ts, RPMDBI_PACKAGES, NULL, 0);
+ }
qva->qva_rc = rpmgiSetArgs(qva->qva_gi, argv, ftsOpts, RPMGI_NONE);
if (qva->qva_gi != NULL && (qva->qva_gi->flags & RPMGI_TSADD)) /* Load the ts with headers. */
Index: lib/rpmcli.h
===================================================================
--- lib/rpmcli.h.orig
+++ lib/rpmcli.h
@@ -165,7 +165,7 @@ typedef enum rpmQueryFlags_e {
QUERY_SCRIPT = (1 << 18), /*!< verify: from --noscripts */
QUERY_DIGEST = (1 << 19), /*!< verify: from --nodigest */
QUERY_SIGNATURE = (1 << 20), /*!< verify: from --nosignature */
- QUERY_PATCHES = (1 << 21), /*!< verify: from --nopatches */
+ QUERY_FOR_PATCHES = (1 << 21), /*!< verify: from --patches */
QUERY_HDRCHK = (1 << 22), /*!< verify: from --nohdrchk */
/*@=enummemuse@*/
QUERY_FOR_LIST = (1 << 23), /*!< query: from --list */
Index: lib/rpmds.c
===================================================================
--- lib/rpmds.c.orig
+++ lib/rpmds.c
@@ -87,6 +87,10 @@ fprintf(stderr, "*** ds %p\t%s[%d]\n", d
tagEVR = RPMTAG_TRIGGERVERSION;
tagF = RPMTAG_TRIGGERFLAGS;
} else
+ if (ds->tagN == RPMTAG_PATCHESNAME) {
+ tagEVR = RPMTAG_PATCHESVERSION;
+ tagF = RPMTAG_PATCHESFLAGS;
+ } else
return NULL;
/*@-branchstate@*/
@@ -325,6 +329,11 @@ rpmds rpmdsNew(Header h, rpmTag tagN, in
tagEVR = RPMTAG_ENHANCESVERSION;
tagF = RPMTAG_ENHANCESFLAGS;
} else
+ if (tagN == RPMTAG_PATCHESNAME) {
+ Type = "patches";
+ tagEVR = RPMTAG_PATCHESVERSION;
+ tagF = RPMTAG_PATCHESFLAGS;
+ } else
goto exit;
/*@-branchstate@*/
@@ -1127,14 +1136,28 @@ void rpmdsProblem(rpmps ps, const char *
if (DNEVR == NULL) DNEVR = "? ?N? ?OP? ?EVR?";
/*@=branchstate@*/
- rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
- pkgNEVR, ds->Type, DNEVR+2);
-
switch ((unsigned)DNEVR[0]) {
case 'C': type = RPMPROB_CONFLICT; break;
default:
case 'R': type = RPMPROB_REQUIRES; break;
}
+ if (DNEVR[0] == 'p') {
+ const char *d;
+ char *dn;
+ rpmds pds = rpmdsInit(ds);
+ dn = xstrdup("p ");
+ while (rpmdsNext(pds) >= 0) {
+ d = rpmdsDNEVR(ds) + 2;
+ dn = xrealloc(dn, strlen(dn) + strlen(d) + 4);
+ if (dn[2])
+ strcat(dn, " | ");
+ strcat(dn, d);
+ }
+ DNEVR = (const char *)dn;
+ }
+
+ rpmMessage(RPMMESS_DEBUG, _("package %s has unsatisfied %s: %s\n"),
+ pkgNEVR, ds->Type, DNEVR+2);
key = (suggestedKeys ? suggestedKeys[0] : NULL);
rpmpsAppend(ps, type, pkgNEVR, key, NULL, NULL, DNEVR, adding);
Index: lib/rpminstall.c
===================================================================
--- lib/rpminstall.c.orig
+++ lib/rpminstall.c
@@ -683,6 +683,11 @@ maybe_manifest:
/*@=branchstate@*/
}
ps = rpmpsFree(ps);
+ } else if (eiu->numRPMS) {
+ /* needed in rpmtsOrder */
+ rpmalMakeIndex(ts->addedPackages);
+ /* need patch references */
+ rpmtsPatchCheck(ts);
}
if (eiu->numRPMS && !(ia->installInterfaceFlags & INSTALL_NOORDER)) {
@@ -789,7 +794,7 @@ int rpmErase(rpmts ts, struct rpmInstall
{ int notifyFlags;
notifyFlags = ia->eraseInterfaceFlags | (rpmIsVerbose() ? INSTALL_LABEL : 0 );
xx = rpmtsSetNotifyCallback(ts,
- rpmShowProgress, (void *) ((long)notifyFlags)
+ rpmShowProgress, (void *) ((long)notifyFlags))
}
#endif
Index: lib/rpmlibprov.c
===================================================================
--- lib/rpmlibprov.c.orig
+++ lib/rpmlibprov.c
@@ -33,6 +33,9 @@ static struct rpmlibProvides_s rpmlibPro
{ "rpmlib(PayloadIsBzip2)", "3.0.5-1",
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
N_("package payload can be compressed using bzip2.") },
+ { "rpmlib(PatchRPMs)", "3.0.6-1",
+ (RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
+ N_("understand rpms that replace a subset of files.") },
{ "rpmlib(PayloadFilesHavePrefix)", "4.0-1",
(RPMSENSE_RPMLIB|RPMSENSE_EQUAL),
N_("package payload file(s) have \"./\" prefix.") },
Index: lib/rpmte.c
===================================================================
--- lib/rpmte.c.orig
+++ lib/rpmte.c
@@ -64,6 +64,7 @@ static void delTE(rpmte p)
p->NEVRA = _free(p->NEVRA);
p->h = headerFree(p->h);
+ p->hPatched = headerFree(p->hPatched);
/*@-boundswrite@*/
memset(p, 0, sizeof(*p)); /* XXX trash and burn */
@@ -183,6 +184,9 @@ static void addTE(rpmts ts, rpmte p, Hea
p->requires = rpmdsNew(h, RPMTAG_REQUIRENAME, scareMem);
p->conflicts = rpmdsNew(h, RPMTAG_CONFLICTNAME, scareMem);
p->obsoletes = rpmdsNew(h, RPMTAG_OBSOLETENAME, scareMem);
+ p->patches = rpmdsNew(h, RPMTAG_PATCHESNAME, scareMem | 2);
+ p->hPatched = NULL;
+ p->isPatchRefresh = 0;
savep = rpmtsSetRelocateElement(ts, p);
p->fi = rpmfiNew(ts, h, RPMTAG_BASENAMES, scareMem);
@@ -520,6 +524,9 @@ rpmds rpmteDS(rpmte te, rpmTag tag)
if (tag == RPMTAG_OBSOLETENAME)
return te->obsoletes;
else
+ if (tag == RPMTAG_PATCHESNAME)
+ return te->patches;
+ else
return NULL;
/*@=compdef =refcounttrans =retalias =retexpose =usereleased @*/
}
Index: lib/rpmte.h
===================================================================
--- lib/rpmte.h.orig
+++ lib/rpmte.h
@@ -115,6 +115,9 @@ struct rpmte_s {
int autorelocatex; /*!< (TR_ADDED) Auto relocation entry index. */
/*@refcounted@*/ /*@null@*/
FD_t fd; /*!< (TR_ADDED) Payload file descriptor. */
+ rpmds patches; /*!< Patches: dependencies. */
+ Header hPatched; /*!< (TR_ADDED) Header of package we patch */
+ int isPatchRefresh; /*!< (TR_ADDED) is a patch refresh */
/*@-fielduse@*/ /* LCL: confused by union? */
union {
Index: lib/transaction.c
===================================================================
--- lib/transaction.c.orig
+++ lib/transaction.c
@@ -199,6 +199,11 @@ static int handleInstInstalledFiles(cons
int rConflicts;
rConflicts = reportConflicts;
+ if (rConflicts && p->hPatched && p->isPatchRefresh) {
+ /* If same package (patch refresh) turn off conflicts */
+ /* Handling of unpatched files not worth the trouble */
+ rConflicts = 0;
+ }
/* Resolve file conflicts to prefer Elf64 (if not forced). */
if (tscolor != 0 && FColor != 0 && FColor != oFColor)
{
@@ -975,6 +980,176 @@ rpmfi rpmtsiFi(const rpmtsi tsi)
/*@=compdef =refcounttrans =usereleased @*/
}
+static int_32 *dupint32(int_32 *old, int cnt)
+{
+ int i;
+ int_32 *new = xmalloc(cnt * sizeof(int_32));
+ for (i = 0; i < cnt; i++)
+ new[i] = old[i];
+ return new;
+}
+
+static void patchUnpatchedFiles(Header oldh, Header h, int isRefresh)
+{
+ int fileCount, oldfileCount, i, j, oldidx, oldidxj;
+ const char ** baseNames, ** dirNames;
+ int_32 * dirIndexes;
+ int_32 * fileMtimes;
+ int_32 * fileSizes;
+ int_32 * fileFlags;
+ char ** fileMd5s;
+ const char ** oldbaseNames, ** olddirNames;
+ int_32 * olddirIndexes;
+ int_32 * oldfileMtimes;
+ int_32 * oldfileSizes;
+ int_32 * oldfileFlags;
+ char ** oldfileMd5s;
+ const char * name, * version, * release;
+ char * evr;
+ int_32 sense;
+ int_32 *epochp;
+ int save = 0;
+ char epoch[20];
+ const char ** oldpatches, **oldpatchesEVR = NULL;
+ int_32 * oldpatchesFlags;
+ int oldpatchesCount;
+
+ if (!oldh) {
+ headerRemoveEntry(h, RPMTAG_PATCHESNAME);
+ headerRemoveEntry(h, RPMTAG_PATCHESFLAGS);
+ headerRemoveEntry(h, RPMTAG_PATCHESVERSION);
+#if 1
+ name = "(none)";
+ sense = 0;
+ evr = "";
+ headerAddEntry(h, RPMTAG_PATCHESNAME, RPM_STRING_ARRAY_TYPE, &name, 1);
+ headerAddEntry(h, RPMTAG_PATCHESFLAGS, RPM_INT32_TYPE, &sense, 1);
+ headerAddEntry(h, RPMTAG_PATCHESVERSION, RPM_STRING_ARRAY_TYPE, &evr, 1);
+#endif
+ return;
+ }
+ if (!headerGetEntry(h, RPMTAG_BASENAMES, NULL,
+ (void **) &baseNames, &fileCount))
+ return;
+ headerGetEntry(h, RPMTAG_DIRNAMES, NULL,
+ (void **) &dirNames, NULL);
+ headerGetEntry(h, RPMTAG_DIRINDEXES, NULL,
+ (void **) &dirIndexes, NULL);
+ headerGetEntry(h, RPMTAG_FILESIZES, NULL,
+ (void **) &fileSizes, NULL);
+ headerGetEntry(h, RPMTAG_FILEMD5S, NULL,
+ (void **) &fileMd5s, NULL);
+ headerGetEntry(h, RPMTAG_FILEMTIMES, NULL,
+ (void **) &fileMtimes, NULL);
+ headerGetEntry(h, RPMTAG_FILEFLAGS, NULL,
+ (void **) &fileFlags, NULL);
+
+ if (!headerGetEntry(oldh, RPMTAG_BASENAMES, NULL,
+ (void **) &oldbaseNames, &oldfileCount))
+ return;
+ headerGetEntry(oldh, RPMTAG_DIRNAMES, NULL,
+ (void **) &olddirNames, NULL);
+ headerGetEntry(oldh, RPMTAG_DIRINDEXES, NULL,
+ (void **) &olddirIndexes, NULL);
+ headerGetEntry(oldh, RPMTAG_FILESIZES, NULL,
+ (void **) &oldfileSizes, NULL);
+ headerGetEntry(oldh, RPMTAG_FILEMD5S, NULL,
+ (void **) &oldfileMd5s, NULL);
+ headerGetEntry(oldh, RPMTAG_FILEMTIMES, NULL,
+ (void **) &oldfileMtimes, NULL);
+ headerGetEntry(oldh, RPMTAG_FILEFLAGS, NULL,
+ (void **) &oldfileFlags, NULL);
+
+ oldidx = -1;
+ oldidxj = 0;
+ for (i = 0; i < fileCount; i++) {
+ if (!(fileFlags[i] & RPMFILE_UNPATCHED))
+ continue;
+ if (dirIndexes[i] != oldidx) {
+ for (j = 0; j < oldfileCount; j++)
+ if (strcmp(dirNames[dirIndexes[i]], olddirNames[olddirIndexes[j]]) == 0)
+ break;
+ if (j == oldfileCount) {
+ while (i + 1 < fileCount && dirIndexes[i] == dirIndexes[i + 1])
+ i++;
+ continue;
+ }
+ oldidx = olddirIndexes[j];
+ oldidxj = j;
+ }
+ for (j = oldidxj; j < oldfileCount; j++)
+ if (olddirIndexes[j] == oldidx && !strcmp(baseNames[i], oldbaseNames[j])) {
+ if (!save) {
+ /* duplicate fileSizes, fileMtimes, fileFlags
+ * so we can modify them */
+ fileSizes = dupint32(fileSizes, fileCount);
+ fileMtimes = dupint32(fileMtimes, fileCount);
+ fileFlags = dupint32(fileFlags, fileCount);
+ }
+ fileSizes[i] = oldfileSizes[j];
+ fileMtimes[i] = oldfileMtimes[j];
+ fileMd5s[i] = oldfileMd5s[j];
+ fileFlags[i] = oldfileFlags[j] | RPMFILE_UNPATCHED;
+ save = 1;
+ break;
+ }
+ }
+ if (save) {
+ headerModifyEntry(h, RPMTAG_FILESIZES, RPM_INT32_TYPE,
+ (void *) fileSizes, fileCount);
+ headerModifyEntry(h, RPMTAG_FILEMD5S, RPM_STRING_ARRAY_TYPE,
+ (void *) fileMd5s, fileCount);
+ headerModifyEntry(h, RPMTAG_FILEMTIMES, RPM_INT32_TYPE,
+ (void *) fileMtimes, fileCount);
+ headerModifyEntry(h, RPMTAG_FILEFLAGS, RPM_INT32_TYPE,
+ (void *) fileFlags, fileCount);
+ free(fileSizes);
+ free(fileMtimes);
+ free(fileFlags);
+ }
+ free(baseNames);
+ free(dirNames);
+ free(fileMd5s);
+ free(oldbaseNames);
+ free(olddirNames);
+ free(oldfileMd5s);
+
+ if (isRefresh) {
+ /* same patch installed, this is just a refresh operation */
+ headerRemoveEntry(h, RPMTAG_PATCHESNAME);
+ headerRemoveEntry(h, RPMTAG_PATCHESFLAGS);
+ headerRemoveEntry(h, RPMTAG_PATCHESVERSION);
+ if (headerGetEntry(oldh, RPMTAG_PATCHESNAME, NULL, (void **) &oldpatches, &oldpatchesCount) && oldpatchesCount) {
+ headerGetEntry(oldh, RPMTAG_PATCHESFLAGS, NULL, (void **) &oldpatchesFlags, &oldpatchesCount);
+ headerGetEntry(oldh, RPMTAG_PATCHESVERSION, NULL, (void **) &oldpatchesEVR, &oldpatchesCount);
+ headerAddEntry(h, RPMTAG_PATCHESNAME, RPM_STRING_ARRAY_TYPE, oldpatches, oldpatchesCount);
+ headerAddEntry(h, RPMTAG_PATCHESFLAGS, RPM_INT32_TYPE, oldpatchesFlags, oldpatchesCount);
+ headerAddEntry(h, RPMTAG_PATCHESVERSION, RPM_STRING_ARRAY_TYPE, oldpatchesEVR, oldpatchesCount);
+ free(oldpatches);
+ free(oldpatchesEVR);
+ }
+ return;
+ }
+ headerNVR(oldh, &name, &version, &release);
+ *epoch = 0;
+ if (headerGetEntry(h, RPMTAG_EPOCH, NULL, (void **) &epochp, NULL))
+ sprintf(epoch, "%d:", *epochp);
+ evr = xmalloc(strlen(epoch) + strlen(version) + strlen(release) + 2);
+ strcpy(evr, epoch);
+ strcat(evr, version);
+ strcat(evr, "-");
+ strcat(evr, release);
+ sense = RPMSENSE_EQUAL;
+ headerRemoveEntry(h, RPMTAG_PATCHESNAME);
+ headerRemoveEntry(h, RPMTAG_PATCHESFLAGS);
+ headerRemoveEntry(h, RPMTAG_PATCHESVERSION);
+ headerAddEntry(h, RPMTAG_PATCHESNAME, RPM_STRING_ARRAY_TYPE, &name, 1);
+ headerAddEntry(h, RPMTAG_PATCHESFLAGS, RPM_INT32_TYPE, &sense, 1);
+ headerAddEntry(h, RPMTAG_PATCHESVERSION, RPM_STRING_ARRAY_TYPE, &evr, 1);
+ free(evr);
+}
+
+
/**
* This is not a generalized function to be called from outside
* librpm. It is called internally by rpmtsRun() to rollback
@@ -2154,6 +2329,8 @@ assert(psm != NULL);
}
psm->fi = rpmfiLink(p->fi, NULL);
+ if (p->hPatched || rpmteDS(p, RPMTAG_PATCHESNAME))
+ patchUnpatchedFiles(p->hPatched, p->fi->h, p->isPatchRefresh);
/*@-nullstate@*/ /* FIX: psm->fi may be NULL */
if (rpmpsmStage(psm, PSM_PKGINSTALL)) {
ourrc++;
Index: doc/rpm.8
===================================================================
--- doc/rpm.8.orig
+++ doc/rpm.8
@@ -68,7 +68,8 @@ rpm \- RPM Package Manager
[\fB\fIPACKAGE_NAME\fB\fR] [\fB-a,--all\fR] [\fB-f,--file \fIFILE\fB\fR]
- [\fB-g,--group \fIGROUP\fB\fR] {\fB-p,--package \fIPACKAGE_FILE\fB\fR]
+ [\fB-g,--group \fIGROUP\fB\fR] [\fB-p,--package \fIPACKAGE_FILE\fB\fR]
+ [\fB-P,--patches\fR]
[\fB--fileid \fIMD5\fB\fR] [\fB--hdrid \fISHA1\fB\fR] [\fB--pkgid \fIMD5\fB\fR] [\fB--tid \fITID\fB\fR]
[\fB--querybynumber \fIHDRNUM\fB\fR] [\fB--triggeredby \fIPACKAGE_NAME\fB\fR]
[\fB--whatprovides \fICAPABILITY\fB\fR] [\fB--whatrequires \fICAPABILITY\fB\fR]
@@ -77,7 +78,8 @@ rpm \- RPM Package Manager
.PP
- [\fB--changelog\fR] [\fB-c,--configfiles\fR] [\fB-d,--docfiles\fR] [\fB--dump\fR]
+ [\fB--basedon\fR] [\fB--changelog\fR] [\fB-c,--configfiles\fR]
+ [\fB-d,--docfiles\fR] [\fB--dump\fR]
[\fB--filesbypkg\fR] [\fB-i,--info\fR] [\fB--last\fR] [\fB-l,--list\fR]
[\fB--provides\fR] [\fB--qf,--queryformat \fIQUERYFMT\fB\fR]
[\fB-R,--requires\fR] [\fB--scripts\fR] [\fB-s,--state\fR]
@@ -547,6 +549,10 @@ that will be expanded to paths that are
the package manifest as additional \fIPACKAGE_FILE\fR
arguments to the query.
.TP
+\fB-P, --patches\fP
+Limit the selected packages to patch-rpms. As a side effect, limit
+the file list to patched files.
+.TP
\fB--pkgid \fIMD5\fB\fR
Query package that contains a given package identifier, i.e. the
\fIMD5\fR digest of the combined header and
@@ -581,6 +587,10 @@ Query all packages that requires \fICAPA
.SS "PACKAGE QUERY OPTIONS:"
.PP
.TP
+\fB--basedon\fR
+Show what packages a patch-rpm is based on. A patch-rpm can only be
+installed if one of the packages it is based on is installed.
+.TP
\fB--changelog\fR
Display change information for the package.
.TP
@@ -613,7 +623,8 @@ Orders the package listing by install ti
packages are at the top.
.TP
\fB-l, --list\fR
-List files in package.
+List files in package. If the \fB\-P\fP option is also given, only
+patched files are shown.
.TP
\fB--provides\fR
List capabilities this package provides.
Index: rpmpopt.in
===================================================================
--- rpmpopt.in.orig
+++ rpmpopt.in
@@ -84,6 +84,10 @@ rpm alias --supplements --qf \
"[%|ENHANCESFLAGS:depflag_strong?{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \
--POPTdesc=$"list capabilities this package supplements"
+rpm alias --basedon --qf \
+ "[%{PATCHESNAME} %{PATCHESFLAGS:depflags} %{PATCHESVERSION}\n]" \
+ --POPTdesc=$"list packages this patch-rpm is based on"
+
rpm alias --info --qf 'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n\
Version : %-27{VERSION} Vendor: %{VENDOR}\n\
Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\
@@ -378,6 +382,10 @@ rpmq alias --supplements --qf \
"[%|ENHANCESFLAGS:depflag_strong?{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \
--POPTdesc=$"list capabilities this package supplements"
+rpmq alias --basedon --qf \
+ "[%{PATCHESNAME} %{PATCHESFLAGS:depflags} %{PATCHESVERSION}\n]" \
+ --POPTdesc=$"list packages this patch-rpm is based on"
+
rpmq alias --info --qf 'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n\
Version : %-27{VERSION} Vendor: %{VENDOR}\n\
Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\
@@ -496,6 +504,10 @@ rpmquery alias --supplements --qf \
"[%|ENHANCESFLAGS:depflag_strong?{%{ENHANCESNAME} %{ENHANCESFLAGS:depflags} %{ENHANCESVERSION}\n}|]" \
--POPTdesc=$"list capabilities this package supplements"
+rpmquery alias --basedon --qf \
+ "[%{PATCHESNAME} %{PATCHESFLAGS:depflags} %{PATCHESVERSION}\n]" \
+ --POPTdesc=$"list packages this patch-rpm is based on"
+
rpmquery alias --info --qf 'Name : %-27{NAME} Relocations: %|PREFIXES?{[%{PREFIXES} ]}:{(not relocatable)}|\n\
Version : %-27{VERSION} Vendor: %{VENDOR}\n\
Release : %-27{RELEASE} Build Date: %{BUILDTIME:date}\n\