10 #include "lib/legacy.h"
13 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
16 * Open a file descriptor to verify file MD5 and size.
17 * @param path file path
18 * @retval pidp prelink helper pid or 0
19 * @retval fsizep file size
20 * @return -1 on error, otherwise, an open file descriptor
24 static int dncmp(const void * a, const void * b)
26 const char *const * first = a;
27 const char *const * second = b;
28 return strcmp(*first, *second);
31 void compressFilelist(Header h)
33 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
34 HAE_t hae = (HAE_t)headerAddEntry;
35 HRE_t hre = (HRE_t)headerRemoveEntry;
36 HFD_t hfd = headerFreeData;
38 const char ** dirNames;
39 const char ** baseNames;
40 uint32_t * dirIndexes;
47 * This assumes the file list is already sorted, and begins with a
48 * single '/'. That assumption isn't critical, but it makes things go
52 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
53 xx = hre(h, RPMTAG_OLDFILENAMES);
54 return; /* Already converted. */
57 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
58 return; /* no file list */
59 if (fileNames == NULL || count <= 0)
62 dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
63 baseNames = alloca(sizeof(*dirNames) * count);
64 dirIndexes = alloca(sizeof(*dirIndexes) * count);
66 if (fileNames[0][0] != '/') {
67 /* HACK. Source RPM, so just do things differently */
69 dirNames[dirIndex] = "";
70 for (i = 0; i < count; i++) {
71 dirIndexes[i] = dirIndex;
72 baseNames[i] = fileNames[i];
77 for (i = 0; i < count; i++) {
83 if (fileNames[i] == NULL) /* XXX can't happen */
85 baseName = strrchr(fileNames[i], '/') + 1;
86 len = baseName - fileNames[i];
91 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
92 char *s = alloca(len + 1);
93 memcpy(s, fileNames[i], len + 1);
95 dirIndexes[i] = ++dirIndex;
96 dirNames[dirIndex] = s;
98 dirIndexes[i] = needle - dirNames;
100 *baseName = savechar;
101 baseNames[i] = baseName;
106 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
107 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
109 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
110 dirNames, dirIndex + 1);
113 fileNames = hfd(fileNames, fnt);
115 xx = hre(h, RPMTAG_OLDFILENAMES);
118 void rpmfiBuildFNames(Header h, rpmTag tagN,
119 const char *** fnp, int * fcp)
121 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
122 HFD_t hfd = headerFreeData;
123 const char ** baseNames;
124 const char ** dirNames;
125 uint32_t * dirIndexes;
127 const char ** fileNames;
129 rpmTag dirNameTag = 0;
130 rpmTag dirIndexesTag = 0;
135 if (tagN == RPMTAG_BASENAMES) {
136 dirNameTag = RPMTAG_DIRNAMES;
137 dirIndexesTag = RPMTAG_DIRINDEXES;
138 } else if (tagN == RPMTAG_ORIGBASENAMES) {
139 dirNameTag = RPMTAG_ORIGDIRNAMES;
140 dirIndexesTag = RPMTAG_ORIGDIRINDEXES;
143 if (!hge(h, tagN, &bnt, (void **) &baseNames, &count)) {
144 if (fnp) *fnp = NULL;
146 return; /* no file list */
149 xx = hge(h, dirNameTag, &dnt, (void **) &dirNames, NULL);
150 xx = hge(h, dirIndexesTag, NULL, (void **) &dirIndexes, &count);
152 size = sizeof(*fileNames) * count;
153 for (i = 0; i < count; i++)
154 size += strlen(baseNames[i]) + strlen(dirNames[dirIndexes[i]]) + 1;
156 fileNames = xmalloc(size);
157 t = ((char *) fileNames) + (sizeof(*fileNames) * count);
158 for (i = 0; i < count; i++) {
160 t = stpcpy( stpcpy(t, dirNames[dirIndexes[i]]), baseNames[i]);
163 baseNames = hfd(baseNames, bnt);
164 dirNames = hfd(dirNames, dnt);
169 fileNames = _free(fileNames);
170 if (fcp) *fcp = count;
173 void expandFilelist(Header h)
175 HAE_t hae = (HAE_t)headerAddEntry;
176 HRE_t hre = (HRE_t)headerRemoveEntry;
177 const char ** fileNames = NULL;
181 if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
182 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
183 if (fileNames == NULL || count <= 0)
185 xx = hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
187 fileNames = _free(fileNames);
190 xx = hre(h, RPMTAG_DIRNAMES);
191 xx = hre(h, RPMTAG_BASENAMES);
192 xx = hre(h, RPMTAG_DIRINDEXES);
196 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
197 * Retrofit an explicit "Provides: name = epoch:version-release.
199 void providePackageNVR(Header h)
201 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
202 HFD_t hfd = headerFreeData;
203 const char *name, *version, *release;
207 int32_t pFlags = RPMSENSE_EQUAL;
208 const char ** provides = NULL;
209 const char ** providesEVR = NULL;
211 int32_t * provideFlags = NULL;
216 /* Generate provides for this package name-version-release. */
217 xx = headerNVR(h, &name, &version, &release);
218 if (!(name && version && release))
220 pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
222 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
223 sprintf(p, "%d:", *epoch);
227 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
230 * Rpm prior to 3.0.3 does not have versioned provides.
231 * If no provides at all are available, we can just add.
233 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
237 * Otherwise, fill in entries on legacy packages.
239 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) {
240 for (i = 0; i < providesCount; i++) {
242 int32_t fdummy = RPMSENSE_ANY;
243 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
245 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
251 xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
253 /* LCL: providesEVR is not NULL */
254 if (provides && providesEVR && provideFlags)
255 for (i = 0; i < providesCount; i++) {
256 if (!(provides[i] && providesEVR[i]))
258 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
259 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
266 provides = hfd(provides, pnt);
267 providesEVR = hfd(providesEVR, pvt);
270 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
272 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
274 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
279 void legacyRetrofit(Header h)
284 * We don't use these entries (and rpm >= 2 never has) and they are
285 * pretty misleading. Let's just get rid of them so they don't confuse
288 if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
289 (void) headerRemoveEntry(h, RPMTAG_FILEUIDS);
290 if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
291 (void) headerRemoveEntry(h, RPMTAG_FILEGIDS);
294 * We switched the way we do relocatable packages. We fix some of
295 * it up here, though the install code still has to be a bit
296 * careful. This fixup makes queries give the new values though,
297 * which is quite handy.
299 if (headerGetEntry(h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &prefix, NULL))
301 const char * nprefix = stripTrailingChar(alloca_strdup(prefix), '/');
302 (void) headerAddEntry(h, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
307 * The file list was moved to a more compressed format which not
308 * only saves memory (nice), but gives fingerprinting a nice, fat
309 * speed boost (very nice). Go ahead and convert old headers to
310 * the new style (this is a noop for new headers).
314 /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
315 if (!headerIsEntry(h, RPMTAG_SOURCERPM)) {
317 if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
318 (void) headerAddEntry(h, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
321 /* Retrofit "Provide: name = EVR" for binary packages. */
322 providePackageNVR(h);