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"
17 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
21 static int dncmp(const void * a, const void * b)
23 const char *const * first = a;
24 const char *const * second = b;
25 return strcmp(*first, *second);
28 void compressFilelist(Header h)
30 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
31 HAE_t hae = (HAE_t)headerAddEntry;
32 HRE_t hre = (HRE_t)headerRemoveEntry;
33 HFD_t hfd = headerFreeData;
35 const char ** dirNames;
36 const char ** baseNames;
37 uint32_t * dirIndexes;
44 * This assumes the file list is already sorted, and begins with a
45 * single '/'. That assumption isn't critical, but it makes things go
49 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
50 xx = hre(h, RPMTAG_OLDFILENAMES);
51 return; /* Already converted. */
54 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (rpm_data_t *) &fileNames, &count))
55 return; /* no file list */
56 if (fileNames == NULL || count <= 0)
59 dirNames = xmalloc(sizeof(*dirNames) * count); /* worst case */
60 baseNames = xmalloc(sizeof(*dirNames) * count);
61 dirIndexes = xmalloc(sizeof(*dirIndexes) * count);
63 if (fileNames[0][0] != '/') {
64 /* HACK. Source RPM, so just do things differently */
66 dirNames[dirIndex] = "";
67 for (i = 0; i < count; i++) {
68 dirIndexes[i] = dirIndex;
69 baseNames[i] = fileNames[i];
74 for (i = 0; i < count; i++) {
80 if (fileNames[i] == NULL) /* XXX can't happen */
82 baseName = strrchr(fileNames[i], '/') + 1;
83 len = baseName - fileNames[i];
88 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
89 char *s = alloca(len + 1);
90 memcpy(s, fileNames[i], len + 1);
92 dirIndexes[i] = ++dirIndex;
93 dirNames[dirIndex] = s;
95 dirIndexes[i] = needle - dirNames;
98 baseNames[i] = baseName;
103 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
104 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
106 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
107 dirNames, (rpm_count_t) dirIndex + 1);
110 fileNames = hfd(fileNames, fnt);
115 xx = hre(h, RPMTAG_OLDFILENAMES);
118 void expandFilelist(Header h)
120 HAE_t hae = (HAE_t)headerAddEntry;
121 HRE_t hre = (HRE_t)headerRemoveEntry;
122 const char ** fileNames = NULL;
123 rpm_count_t count = 0;
126 if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
127 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
128 if (fileNames == NULL || count <= 0)
130 xx = hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
132 fileNames = _free(fileNames);
135 xx = hre(h, RPMTAG_DIRNAMES);
136 xx = hre(h, RPMTAG_BASENAMES);
137 xx = hre(h, RPMTAG_DIRINDEXES);
141 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
142 * Retrofit an explicit "Provides: name = epoch:version-release.
144 void providePackageNVR(Header h)
146 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
147 HFD_t hfd = headerFreeData;
148 const char *name, *version, *release;
152 rpmsenseFlags pFlags = RPMSENSE_EQUAL;
153 const char ** provides = NULL;
154 const char ** providesEVR = NULL;
155 rpm_tagtype_t pnt, pvt;
156 rpmsenseFlags * provideFlags = NULL;
157 rpm_count_t providesCount, i;
161 /* Generate provides for this package name-version-release. */
162 xx = headerNVR(h, &name, &version, &release);
163 if (!(name && version && release))
165 pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
167 if (hge(h, RPMTAG_EPOCH, NULL, (rpm_data_t *) &epoch, NULL)) {
168 sprintf(p, "%d:", *epoch);
172 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
175 * Rpm prior to 3.0.3 does not have versioned provides.
176 * If no provides at all are available, we can just add.
178 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (rpm_data_t *) &provides, &providesCount))
182 * Otherwise, fill in entries on legacy packages.
184 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (rpm_data_t *) &providesEVR, NULL)) {
185 for (i = 0; i < providesCount; i++) {
186 const char * vdummy = "";
187 rpmsenseFlags fdummy = RPMSENSE_ANY;
188 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
190 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
196 xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (rpm_data_t *) &provideFlags, NULL);
198 /* LCL: providesEVR is not NULL */
199 if (provides && providesEVR && provideFlags)
200 for (i = 0; i < providesCount; i++) {
201 if (!(provides[i] && providesEVR[i]))
203 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
204 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
211 provides = hfd(provides, pnt);
212 providesEVR = hfd(providesEVR, pvt);
215 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
217 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
219 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
224 void legacyRetrofit(Header h)
229 * We don't use these entries (and rpm >= 2 never has) and they are
230 * pretty misleading. Let's just get rid of them so they don't confuse
233 if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
234 (void) headerRemoveEntry(h, RPMTAG_FILEUIDS);
235 if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
236 (void) headerRemoveEntry(h, RPMTAG_FILEGIDS);
239 * We switched the way we do relocatable packages. We fix some of
240 * it up here, though the install code still has to be a bit
241 * careful. This fixup makes queries give the new values though,
242 * which is quite handy.
244 if (headerGetEntry(h, RPMTAG_DEFAULTPREFIX, NULL, (rpm_data_t *) &prefix, NULL))
246 const char * nprefix = stripTrailingChar(alloca_strdup(prefix), '/');
247 (void) headerAddEntry(h, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
252 * The file list was moved to a more compressed format which not
253 * only saves memory (nice), but gives fingerprinting a nice, fat
254 * speed boost (very nice). Go ahead and convert old headers to
255 * the new style (this is a noop for new headers).
259 /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
260 if (headerIsSource(h)) {
262 if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
263 (void) headerAddEntry(h, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
266 /* Retrofit "Provide: name = EVR" for binary packages. */
267 providePackageNVR(h);