11 #include "lib/legacy.h"
14 #define alloca_strdup(_s) strcpy(alloca(strlen(_s)+1), (_s))
17 * Open a file descriptor to verify file MD5 and size.
18 * @param path file path
19 * @retval pidp prelink helper pid or 0
20 * @retval fsizep file size
21 * @return -1 on error, otherwise, an open file descriptor
25 static int dncmp(const void * a, const void * b)
27 const char *const * first = a;
28 const char *const * second = b;
29 return strcmp(*first, *second);
32 void compressFilelist(Header h)
34 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
35 HAE_t hae = (HAE_t)headerAddEntry;
36 HRE_t hre = (HRE_t)headerRemoveEntry;
37 HFD_t hfd = headerFreeData;
39 const char ** dirNames;
40 const char ** baseNames;
41 uint32_t * dirIndexes;
48 * This assumes the file list is already sorted, and begins with a
49 * single '/'. That assumption isn't critical, but it makes things go
53 if (headerIsEntry(h, RPMTAG_DIRNAMES)) {
54 xx = hre(h, RPMTAG_OLDFILENAMES);
55 return; /* Already converted. */
58 if (!hge(h, RPMTAG_OLDFILENAMES, &fnt, (void **) &fileNames, &count))
59 return; /* no file list */
60 if (fileNames == NULL || count <= 0)
63 dirNames = alloca(sizeof(*dirNames) * count); /* worst case */
64 baseNames = alloca(sizeof(*dirNames) * count);
65 dirIndexes = alloca(sizeof(*dirIndexes) * count);
67 if (fileNames[0][0] != '/') {
68 /* HACK. Source RPM, so just do things differently */
70 dirNames[dirIndex] = "";
71 for (i = 0; i < count; i++) {
72 dirIndexes[i] = dirIndex;
73 baseNames[i] = fileNames[i];
78 for (i = 0; i < count; i++) {
84 if (fileNames[i] == NULL) /* XXX can't happen */
86 baseName = strrchr(fileNames[i], '/') + 1;
87 len = baseName - fileNames[i];
92 (needle = bsearch(&fileNames[i], dirNames, dirIndex + 1, sizeof(dirNames[0]), dncmp)) == NULL) {
93 char *s = alloca(len + 1);
94 memcpy(s, fileNames[i], len + 1);
96 dirIndexes[i] = ++dirIndex;
97 dirNames[dirIndex] = s;
99 dirIndexes[i] = needle - dirNames;
101 *baseName = savechar;
102 baseNames[i] = baseName;
107 xx = hae(h, RPMTAG_DIRINDEXES, RPM_INT32_TYPE, dirIndexes, count);
108 xx = hae(h, RPMTAG_BASENAMES, RPM_STRING_ARRAY_TYPE,
110 xx = hae(h, RPMTAG_DIRNAMES, RPM_STRING_ARRAY_TYPE,
111 dirNames, dirIndex + 1);
114 fileNames = hfd(fileNames, fnt);
116 xx = hre(h, RPMTAG_OLDFILENAMES);
119 void expandFilelist(Header h)
121 HAE_t hae = (HAE_t)headerAddEntry;
122 HRE_t hre = (HRE_t)headerRemoveEntry;
123 const char ** fileNames = NULL;
127 if (!headerIsEntry(h, RPMTAG_OLDFILENAMES)) {
128 rpmfiBuildFNames(h, RPMTAG_BASENAMES, &fileNames, &count);
129 if (fileNames == NULL || count <= 0)
131 xx = hae(h, RPMTAG_OLDFILENAMES, RPM_STRING_ARRAY_TYPE,
133 fileNames = _free(fileNames);
136 xx = hre(h, RPMTAG_DIRNAMES);
137 xx = hre(h, RPMTAG_BASENAMES);
138 xx = hre(h, RPMTAG_DIRINDEXES);
142 * Up to rpm 3.0.4, packages implicitly provided their own name-version-release.
143 * Retrofit an explicit "Provides: name = epoch:version-release.
145 void providePackageNVR(Header h)
147 HGE_t hge = (HGE_t)headerGetEntryMinMemory;
148 HFD_t hfd = headerFreeData;
149 const char *name, *version, *release;
153 int32_t pFlags = RPMSENSE_EQUAL;
154 const char ** provides = NULL;
155 const char ** providesEVR = NULL;
157 int32_t * provideFlags = NULL;
162 /* Generate provides for this package name-version-release. */
163 xx = headerNVR(h, &name, &version, &release);
164 if (!(name && version && release))
166 pEVR = p = alloca(21 + strlen(version) + 1 + strlen(release) + 1);
168 if (hge(h, RPMTAG_EPOCH, NULL, (void **) &epoch, NULL)) {
169 sprintf(p, "%d:", *epoch);
173 (void) stpcpy( stpcpy( stpcpy(p, version) , "-") , release);
176 * Rpm prior to 3.0.3 does not have versioned provides.
177 * If no provides at all are available, we can just add.
179 if (!hge(h, RPMTAG_PROVIDENAME, &pnt, (void **) &provides, &providesCount))
183 * Otherwise, fill in entries on legacy packages.
185 if (!hge(h, RPMTAG_PROVIDEVERSION, &pvt, (void **) &providesEVR, NULL)) {
186 for (i = 0; i < providesCount; i++) {
188 int32_t fdummy = RPMSENSE_ANY;
189 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
191 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
197 xx = hge(h, RPMTAG_PROVIDEFLAGS, NULL, (void **) &provideFlags, NULL);
199 /* LCL: providesEVR is not NULL */
200 if (provides && providesEVR && provideFlags)
201 for (i = 0; i < providesCount; i++) {
202 if (!(provides[i] && providesEVR[i]))
204 if (!(provideFlags[i] == RPMSENSE_EQUAL &&
205 !strcmp(name, provides[i]) && !strcmp(pEVR, providesEVR[i])))
212 provides = hfd(provides, pnt);
213 providesEVR = hfd(providesEVR, pvt);
216 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDENAME, RPM_STRING_ARRAY_TYPE,
218 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEFLAGS, RPM_INT32_TYPE,
220 xx = headerAddOrAppendEntry(h, RPMTAG_PROVIDEVERSION, RPM_STRING_ARRAY_TYPE,
225 void legacyRetrofit(Header h)
230 * We don't use these entries (and rpm >= 2 never has) and they are
231 * pretty misleading. Let's just get rid of them so they don't confuse
234 if (headerIsEntry(h, RPMTAG_FILEUSERNAME))
235 (void) headerRemoveEntry(h, RPMTAG_FILEUIDS);
236 if (headerIsEntry(h, RPMTAG_FILEGROUPNAME))
237 (void) headerRemoveEntry(h, RPMTAG_FILEGIDS);
240 * We switched the way we do relocatable packages. We fix some of
241 * it up here, though the install code still has to be a bit
242 * careful. This fixup makes queries give the new values though,
243 * which is quite handy.
245 if (headerGetEntry(h, RPMTAG_DEFAULTPREFIX, NULL, (void **) &prefix, NULL))
247 const char * nprefix = stripTrailingChar(alloca_strdup(prefix), '/');
248 (void) headerAddEntry(h, RPMTAG_PREFIXES, RPM_STRING_ARRAY_TYPE,
253 * The file list was moved to a more compressed format which not
254 * only saves memory (nice), but gives fingerprinting a nice, fat
255 * speed boost (very nice). Go ahead and convert old headers to
256 * the new style (this is a noop for new headers).
260 /* XXX binary rpms always have RPMTAG_SOURCERPM, source rpms do not */
261 if (headerIsSource(h)) {
263 if (!headerIsEntry(h, RPMTAG_SOURCEPACKAGE))
264 (void) headerAddEntry(h, RPMTAG_SOURCEPACKAGE, RPM_INT32_TYPE,
267 /* Retrofit "Provide: name = EVR" for binary packages. */
268 providePackageNVR(h);