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 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
29 HAE_t hae = (HAE_t)headerAddEntry;
30 HRE_t hre = (HRE_t)headerRemoveEntry;
31 HFD_t hfd = headerFreeData;
34 const char ** baseNames;
35 uint32_t * dirIndexes;
42 * This assumes the file list is already sorted, and begins with a
43 * single '/'. That assumption isn't critical, but it makes things go
47 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
48 xx = hre(h, RPMTAG_OLDFILENAMES);
49 return; /* Already converted. */
52 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (rpm_data_t *) &fileNames, &count))
53 return; /* no file list */
54 if (fileNames == NULL || count <= 0)
57 dirNames = xmalloc(sizeof(*dirNames) * count); /* worst case */
58 baseNames = xmalloc(sizeof(*dirNames) * count);
59 dirIndexes = xmalloc(sizeof(*dirIndexes) * count);
61 if (fileNames[0][0] != '/') {
62 /* HACK. Source RPM, so just do things differently */
64 dirNames[dirIndex] = xstrdup("");
65 for (i = 0; i < count; i++) {
66 dirIndexes[i] = dirIndex;
67 baseNames[i] = fileNames[i];
72 for (i = 0; i < count; i++) {
78 if (fileNames[i] == NULL) /* XXX can't happen */
80 baseName = strrchr(fileNames[i], '/') + 1;
81 len = baseName - fileNames[i];
86 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
87 char *s = xmalloc(len + 1);
88 rstrlcpy(s, fileNames[i], len + 1);
89 dirIndexes[i] = ++dirIndex;
90 dirNames[dirIndex] = s;
92 dirIndexes[i] = needle - dirNames;
95 baseNames[i] = baseName;
100 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
101 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
103 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
104 dirNames, (rpm_count_t) dirIndex + 1);
107 fileNames = hfd(fileNames, fnt);
108 for (i = 0; i <= dirIndex; i++) {
115 xx = hre(h, RPMTAG_OLDFILENAMES);
118 void expandFilelist(Header h)
120 HRE_t hre = (HRE_t)headerRemoveEntry;
121 struct rpmtd_s filenames;
123 if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
124 (void) headerGet(h, RPMTAG_FILENAMES, &filenames, HEADERGET_EXT);
125 if (rpmtdCount(&filenames) < 1)
127 rpmtdSetTag(&filenames, RPMTAG_OLDFILENAMES);
128 headerPut(h, &filenames, HEADERPUT_DEFAULT);
129 rpmtdFreeData(&filenames);
132 (void) hre(h, RPMTAG_DIRNAMES);
133 (void) hre(h, RPMTAG_BASENAMES);
134 (void) hre(h, RPMTAG_DIRINDEXES);
138 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
139 * Retrofit an explicit "Provides: name = epoch:version-release.
141 static void providePackageNVR(Header h)
143 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
144 HFD_t hfd = headerFreeData;
147 rpmsenseFlags pFlags = RPMSENSE_EQUAL;
148 const char ** provides = NULL;
149 const char ** providesEVR = NULL;
151 rpmsenseFlags * provideFlags = NULL;
152 rpm_count_t providesCount, i;
156 /* Generate provides for this package name-version-release. */
157 pEVR = headerGetEVR(h, &name);
162 * Rpm prior to 3.0.3 does not have versioned provides.
163 * If no provides at all are available, we can just add.
165 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (rpm_data_t *) &provides, &providesCount))
169 * Otherwise, fill in entries on legacy packages.
171 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (rpm_data_t *) &providesEVR, NULL)) {
172 for (i = 0; i < providesCount; i++) {
173 const char * vdummy = "";
174 rpmsenseFlags fdummy = RPMSENSE_ANY;
175 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
177 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
183 xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (rpm_data_t *) &provideFlags, NULL);
185 /* LCL: providesEVR is not NULL */
186 if (provides && providesEVR && provideFlags)
187 for (i = 0; i < providesCount; i++) {
188 if (!(provides[i] && providesEVR[i]))
190 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
191 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
198 provides = hfd(provides, pnt);
199 providesEVR = hfd(providesEVR, pvt);
202 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
204 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
206 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
212 void legacyRetrofit(Header h)
217 * We don't use these entries (and rpm >= 2 never has) and they are
218 * pretty misleading. Let's just get rid of them so they don't confuse
221 if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
222 (void) headerRemoveEntry(h, RPMTAG_FILEUIDS);
223 if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
224 (void) headerRemoveEntry(h, RPMTAG_FILEGIDS);
227 * We switched the way we do relocatable packages. We fix some of
228 * it up here, though the install code still has to be a bit
229 * careful. This fixup makes queries give the new values though,
230 * which is quite handy.
232 if (headerGetEntry(h, RPMTAG_DEFAULTPREFIX, NULL, (rpm_data_t *) &prefix, NULL))
234 char * nprefix = stripTrailingChar(xstrdup(prefix), '/');
235 (void) headerAddEntry(h, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
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);