7 #include <rpm/header.h>
8 #include <rpm/rpmmacro.h>
9 #include <rpm/rpmstring.h>
10 #include <rpm/rpmfi.h>
11 #include <rpm/rpmds.h>
13 #include "lib/legacy.h"
19 static int dncmp(const void * a, const void * b)
21 const char *const * first = a;
22 const char *const * second = b;
23 return strcmp(*first, *second);
26 void compressFilelist(Header h)
28 HAE_t hae = (HAE_t)headerAddEntry;
29 HRE_t hre = (HRE_t)headerRemoveEntry;
30 struct rpmtd_s fileNames;
32 const char ** baseNames;
33 uint32_t * dirIndexes;
39 * This assumes the file list is already sorted, and begins with a
40 * single '/'. That assumption isn't critical, but it makes things go
44 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
45 xx = hre(h, RPMTAG_OLDFILENAMES);
46 return; /* Already converted. */
49 if (!headerGet(h, RPMTAG_OLDFILENAMES, &fileNames, HEADERGET_MINMEM))
51 count = rpmtdCount(&fileNames);
55 dirNames = xmalloc(sizeof(*dirNames) * count); /* worst case */
56 baseNames = xmalloc(sizeof(*dirNames) * count);
57 dirIndexes = xmalloc(sizeof(*dirIndexes) * count);
59 if (headerIsSource(h)) {
60 /* HACK. Source RPM, so just do things differently */
62 dirNames[dirIndex] = xstrdup("");
63 while ((i = rpmtdNext(&fileNames)) >= 0) {
64 dirIndexes[i] = dirIndex;
65 baseNames[i] = rpmtdGetString(&fileNames);
70 while ((i = rpmtdNext(&fileNames)) >= 0) {
75 const char *filename = rpmtdGetString(&fileNames);
77 if (filename == NULL) /* XXX can't happen */
79 baseName = strrchr(filename, '/') + 1;
80 len = baseName - filename;
85 (needle = bsearch(filename, dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
86 char *s = xmalloc(len + 1);
87 rstrlcpy(s, filename, len + 1);
88 dirIndexes[i] = ++dirIndex;
89 dirNames[dirIndex] = s;
91 dirIndexes[i] = needle - dirNames;
94 baseNames[i] = baseName;
99 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
100 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
102 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
103 dirNames, (rpm_count_t) dirIndex + 1);
106 rpmtdFreeData(&fileNames);
107 for (i = 0; i <= dirIndex; i++) {
114 xx = hre(h, RPMTAG_OLDFILENAMES);
117 void expandFilelist(Header h)
119 HRE_t hre = (HRE_t)headerRemoveEntry;
120 struct rpmtd_s filenames;
122 if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
123 (void) headerGet(h, RPMTAG_FILENAMES, &filenames, HEADERGET_EXT);
124 if (rpmtdCount(&filenames) < 1)
126 rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES);
127 headerPut(h, &filenames, HEADERPUT_DEFAULT);
128 rpmtdFreeData(&filenames);
131 (void) hre(h, RPMTAG_DIRNAMES);
132 (void) hre(h, RPMTAG_BASENAMES);
133 (void) hre(h, RPMTAG_DIRINDEXES);
137 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
138 * Retrofit an explicit "Provides: name = epoch:version-release.
140 static void providePackageNVR(Header h)
142 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
143 HFD_t hfd = headerFreeData;
146 rpmsenseFlags pFlags = RPMSENSE_EQUAL;
147 const char ** provides = NULL;
148 const char ** providesEVR = NULL;
150 rpmsenseFlags * provideFlags = NULL;
151 rpm_count_t providesCount, i;
155 /* Generate provides for this package name-version-release. */
156 pEVR = headerGetEVR(h, &name);
161 * Rpm prior to 3.0.3 does not have versioned provides.
162 * If no provides at all are available, we can just add.
164 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (rpm_data_t *) &provides, &providesCount))
168 * Otherwise, fill in entries on legacy packages.
170 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (rpm_data_t *) &providesEVR, NULL)) {
171 for (i = 0; i < providesCount; i++) {
172 const char * vdummy = "";
173 rpmsenseFlags fdummy = RPMSENSE_ANY;
174 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
176 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
182 xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (rpm_data_t *) &provideFlags, NULL);
184 /* LCL: providesEVR is not NULL */
185 if (provides && providesEVR && provideFlags)
186 for (i = 0; i < providesCount; i++) {
187 if (!(provides[i] && providesEVR[i]))
189 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
190 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
197 provides = hfd(provides, pnt);
198 providesEVR = hfd(providesEVR, pvt);
201 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
203 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
205 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
211 void legacyRetrofit(Header h)
213 struct rpmtd_s dprefix;
216 * We don't use these entries (and rpm >= 2 never has) and they are
217 * pretty misleading. Let's just get rid of them so they don't confuse
220 if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
221 (void) headerRemoveEntry(h, RPMTAG_FILEUIDS);
222 if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
223 (void) headerRemoveEntry(h, RPMTAG_FILEGIDS);
226 * We switched the way we do relocatable packages. We fix some of
227 * it up here, though the install code still has to be a bit
228 * careful. This fixup makes queries give the new values though,
229 * which is quite handy.
231 if (headerGet(h, RPMTAG_DEFAULTPREFIX, &dprefix, HEADERGET_MINMEM)) {
232 const char *prefix = rpmtdGetString(&dprefix);
233 char * nprefix = stripTrailingChar(xstrdup(prefix), '/');
234 (void) headerAddEntry(h, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
237 rpmtdFreeData(&dprefix);
241 * The file list was moved to a more compressed format which not
242 * only saves memory (nice), but gives fingerprinting a nice, fat
243 * speed boost (very nice). Go ahead and convert old headers to
244 * the new style (this is a noop for new headers).
248 /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
249 if (headerIsSource(h)) {
251 if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
252 (void) headerAddEntry(h, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
255 /* Retrofit "Provide: name = EVR" for binary packages. */
256 providePackageNVR(h);