Bug Summary

File:lib/rpmal.c
Warning:line 480, column 2
Value stored to 'ret' is never read

Annotated Source Code

1/** \ingroup rpmdep
2 * \file lib/rpmal.c
3 */
4
5#include "system.h"
6
7
8#include <rpm/rpmte.h>
9#include <rpm/rpmfi.h>
10#include <rpm/rpmstrpool.h>
11
12#include "lib/rpmal.h"
13#include "lib/misc.h"
14#include "lib/rpmte_internal.h"
15#include "lib/rpmds_internal.h"
16#include "lib/rpmfi_internal.h"
17
18#include "debug.h"
19
20typedef struct availablePackage_s * availablePackage;
21typedef int rpmalNum;
22
23/** \ingroup rpmdep
24 * Info about a single package to be installed.
25 */
26struct availablePackage_s {
27 rpmte p; /*!< transaction member */
28 rpmds provides; /*!< Provides: dependencies. */
29 rpmds obsoletes; /*!< Obsoletes: dependencies. */
30 rpmfiles fi; /*!< File info set. */
31};
32
33/** \ingroup rpmdep
34 * A single available item (e.g. a Provides: dependency).
35 */
36typedef struct availableIndexEntry_s {
37 rpmalNum pkgNum; /*!< Containing package index. */
38 unsigned int entryIx; /*!< Dependency index. */
39} * availableIndexEntry;
40
41#undef HASHTYPErpmalFileHash
42#undef HTKEYTYPErpmsid
43#undef HTDATATYPEstruct availableIndexFileEntry_s
44#define HASHTYPErpmalFileHash rpmalDepHash
45#define HTKEYTYPErpmsid rpmsid
46#define HTDATATYPEstruct availableIndexFileEntry_s struct availableIndexEntry_s
47#include "lib/rpmhash.H"
48#include "lib/rpmhash.C"
49
50typedef struct availableIndexFileEntry_s {
51 rpmsid dirName;
52 rpmalNum pkgNum; /*!< Containing package index. */
53 unsigned int entryIx; /*!< Dependency index. */
54} * availableIndexFileEntry;
55
56#undef HASHTYPErpmalFileHash
57#undef HTKEYTYPErpmsid
58#undef HTDATATYPEstruct availableIndexFileEntry_s
59#define HASHTYPErpmalFileHash rpmalFileHash
60#define HTKEYTYPErpmsid rpmsid
61#define HTDATATYPEstruct availableIndexFileEntry_s struct availableIndexFileEntry_s
62#include "lib/rpmhash.H"
63#include "lib/rpmhash.C"
64
65/** \ingroup rpmdep
66 * Set of available packages, items, and directories.
67 */
68struct rpmal_s {
69 rpmstrPool pool; /*!< String pool */
70 availablePackage list; /*!< Set of packages. */
71 rpmalDepHash providesHash;
72 rpmalDepHash obsoletesHash;
73 rpmalFileHash fileHash;
74 int delta; /*!< Delta for pkg list reallocation. */
75 int size; /*!< No. of pkgs in list. */
76 int alloced; /*!< No. of pkgs allocated for list. */
77 rpmtransFlags tsflags; /*!< Transaction control flags. */
78 rpm_color_t tscolor; /*!< Transaction color. */
79 rpm_color_t prefcolor; /*!< Transaction preferred color. */
80 fingerPrintCache fpc;
81};
82
83/**
84 * Destroy available item index.
85 * @param al available list
86 */
87static void rpmalFreeIndex(rpmal al)
88{
89 al->providesHash = rpmalDepHashFree(al->providesHash);
90 al->obsoletesHash = rpmalDepHashFree(al->obsoletesHash);
91 al->fileHash = rpmalFileHashFree(al->fileHash);
92 al->fpc = fpCacheFree(al->fpc);
93}
94
95rpmal rpmalCreate(rpmstrPool pool, int delta, rpmtransFlags tsflags,
96 rpm_color_t tscolor, rpm_color_t prefcolor)
97{
98 rpmal al = xcalloc(1, sizeof(*al))rcalloc((1), (sizeof(*al)));
99
100 /* transition time safe-guard */
101 assert(pool != NULL)({ if (pool != ((void*)0)) ; else __assert_fail ("pool != NULL"
, "rpmal.c", 101, __PRETTY_FUNCTION__); })
;
102
103 al->pool = rpmstrPoolLink(pool);
104 al->delta = delta;
105 al->size = 0;
106 al->alloced = al->delta;
107 al->list = xmalloc(sizeof(*al->list) * al->alloced)rmalloc((sizeof(*al->list) * al->alloced));;
108
109 al->providesHash = NULL((void*)0);
110 al->obsoletesHash = NULL((void*)0);
111 al->fileHash = NULL((void*)0);
112 al->tsflags = tsflags;
113 al->tscolor = tscolor;
114 al->prefcolor = prefcolor;
115
116 return al;
117}
118
119rpmal rpmalFree(rpmal al)
120{
121 availablePackage alp;
122 int i;
123
124 if (al == NULL((void*)0))
125 return NULL((void*)0);
126
127 if ((alp = al->list) != NULL((void*)0))
128 for (i = 0; i < al->size; i++, alp++) {
129 alp->obsoletes = rpmdsFree(alp->obsoletes);
130 alp->provides = rpmdsFree(alp->provides);
131 alp->fi = rpmfilesFree(alp->fi);
132 }
133 al->pool = rpmstrPoolFree(al->pool);
134 al->list = _free(al->list)rfree((al->list));
135 al->alloced = 0;
136
137 rpmalFreeIndex(al);
138 al = _free(al)rfree((al));
139 return NULL((void*)0);
140}
141
142static unsigned int sidHash(rpmsid sid)
143{
144 return sid;
145}
146
147static int sidCmp(rpmsid a, rpmsid b)
148{
149 return (a != b);
150}
151
152void rpmalDel(rpmal al, rpmte p)
153{
154 availablePackage alp;
155 rpmalNum pkgNum;
156
157 if (al == NULL((void*)0) || al->list == NULL((void*)0))
158 return; /* XXX can't happen */
159
160 // XXX use a search for self provide
161 for (pkgNum=0; pkgNum<al->size; pkgNum++) {
162 if (al->list[pkgNum].p == p) {
163 break;
164 }
165 }
166 if (pkgNum == al->size ) return; // Not found!
167
168 alp = al->list + pkgNum;
169 // do not actually delete, just set p to NULL
170 // and later filter that out of the results
171 alp->p = NULL((void*)0);
172}
173
174static void rpmalAddFiles(rpmal al, rpmalNum pkgNum, rpmfiles fi)
175{
176 struct availableIndexFileEntry_s fileEntry;
177 int fc = rpmfilesFC(fi);
178 rpm_color_t ficolor;
179 int skipdoc = (al->tsflags & RPMTRANS_FLAG_NODOCS);
180 int skipconf = (al->tsflags & RPMTRANS_FLAG_NOCONFIGS);
181
182 fileEntry.pkgNum = pkgNum;
183
184 for (int i = 0; i < fc; i++) {
185 /* Ignore colored provides not in our rainbow. */
186 ficolor = rpmfilesFColor(fi, i);
187 if (al->tscolor && ficolor && !(al->tscolor & ficolor))
188 continue;
189
190 /* Ignore files that wont be installed */
191 if (skipdoc && (rpmfilesFFlags(fi, i) & RPMFILE_DOC))
192 continue;
193 if (skipconf && (rpmfilesFFlags(fi, i) & RPMFILE_CONFIG))
194 continue;
195
196 fileEntry.dirName = rpmfilesDNId(fi, rpmfilesDI(fi, i));
197 fileEntry.entryIx = i;
198
199 rpmalFileHashAddEntry(al->fileHash, rpmfilesBNId(fi, i), fileEntry);
200 }
201}
202
203static void rpmalAddProvides(rpmal al, rpmalNum pkgNum, rpmds provides)
204{
205 struct availableIndexEntry_s indexEntry;
206 rpm_color_t dscolor;
207 int skipconf = (al->tsflags & RPMTRANS_FLAG_NOCONFIGS);
208 int dc = rpmdsCount(provides);
209
210 indexEntry.pkgNum = pkgNum;
211
212 for (int i = 0; i < dc; i++) {
213 /* Ignore colored provides not in our rainbow. */
214 dscolor = rpmdsColorIndex(provides, i);
215 if (al->tscolor && dscolor && !(al->tscolor & dscolor))
216 continue;
217
218 /* Ignore config() provides if the files wont be installed */
219 if (skipconf & (rpmdsFlagsIndex(provides, i) & RPMSENSE_CONFIG))
220 continue;
221
222 indexEntry.entryIx = i;;
223 rpmalDepHashAddEntry(al->providesHash,
224 rpmdsNIdIndex(provides, i), indexEntry);
225 }
226}
227
228static void rpmalAddObsoletes(rpmal al, rpmalNum pkgNum, rpmds obsoletes)
229{
230 struct availableIndexEntry_s indexEntry;
231 rpm_color_t dscolor;
232 int dc = rpmdsCount(obsoletes);
233
234 indexEntry.pkgNum = pkgNum;
235
236 for (int i = 0; i < dc; i++) {
237 /* Obsoletes shouldn't be colored but just in case... */
238 dscolor = rpmdsColorIndex(obsoletes, i);
239 if (al->tscolor && dscolor && !(al->tscolor & dscolor))
240 continue;
241
242 indexEntry.entryIx = i;;
243 rpmalDepHashAddEntry(al->obsoletesHash,
244 rpmdsNIdIndex(obsoletes, i), indexEntry);
245 }
246}
247
248void rpmalAdd(rpmal al, rpmte p)
249{
250 rpmalNum pkgNum;
251 availablePackage alp;
252
253 if (al->size == al->alloced) {
254 al->alloced += al->delta;
255 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced)rrealloc((al->list), (sizeof(*al->list) * al->alloced
))
;
256 }
257 pkgNum = al->size++;
258
259 alp = al->list + pkgNum;
260
261 alp->p = p;
262
263 alp->provides = rpmdsLink(rpmteDS(p, RPMTAG_PROVIDENAME));
264 alp->obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME));
265 alp->fi = rpmteFiles(p);
266
267 /*
268 * Transition-time safe-guard to catch private-pool uses.
269 * File sets with no files have NULL pool, that's fine. But WTF is up
270 * with the provides: every single package should have at least its
271 * own name as a provide, and thus never NULL, and normal use matches
272 * this expectation. However the test-suite is tripping up on NULL
273 * NULL pool from NULL alp->provides in numerous cases?
274 */
275 {
276 rpmstrPool fipool = rpmfilesPool(alp->fi);
277 rpmstrPool dspool = rpmdsPool(alp->provides);
278
279 assert(fipool == NULL || fipool == al->pool)({ if (fipool == ((void*)0) || fipool == al->pool) ; else __assert_fail
("fipool == NULL || fipool == al->pool", "rpmal.c", 279, __PRETTY_FUNCTION__
); })
;
280 assert(dspool == NULL || dspool == al->pool)({ if (dspool == ((void*)0) || dspool == al->pool) ; else __assert_fail
("dspool == NULL || dspool == al->pool", "rpmal.c", 280, __PRETTY_FUNCTION__
); })
;
281 }
282
283 /* Try to be lazy as delayed hash creation is cheaper */
284 if (al->providesHash != NULL((void*)0))
285 rpmalAddProvides(al, pkgNum, alp->provides);
286 if (al->obsoletesHash != NULL((void*)0))
287 rpmalAddObsoletes(al, pkgNum, alp->obsoletes);
288 if (al->fileHash != NULL((void*)0))
289 rpmalAddFiles(al, pkgNum, alp->fi);
290
291 assert(((rpmalNum)(alp - al->list)) == pkgNum)({ if (((rpmalNum)(alp - al->list)) == pkgNum) ; else __assert_fail
("((rpmalNum)(alp - al->list)) == pkgNum", "rpmal.c", 291
, __PRETTY_FUNCTION__); })
;
292}
293
294static void rpmalMakeFileIndex(rpmal al)
295{
296 availablePackage alp;
297 int i, fileCnt = 0;
298
299 for (i = 0; i < al->size; i++) {
300 alp = al->list + i;
301 if (alp->fi != NULL((void*)0))
302 fileCnt += rpmfilesFC(alp->fi);
303 }
304 al->fileHash = rpmalFileHashCreate(fileCnt/4+128,
305 sidHash, sidCmp, NULL((void*)0), NULL((void*)0));
306 for (i = 0; i < al->size; i++) {
307 alp = al->list + i;
308 rpmalAddFiles(al, i, alp->fi);
309 }
310}
311
312static void rpmalMakeProvidesIndex(rpmal al)
313{
314 availablePackage alp;
315 int i, providesCnt = 0;
316
317 for (i = 0; i < al->size; i++) {
318 alp = al->list + i;
319 providesCnt += rpmdsCount(alp->provides);
320 }
321
322 al->providesHash = rpmalDepHashCreate(providesCnt/4+128,
323 sidHash, sidCmp, NULL((void*)0), NULL((void*)0));
324 for (i = 0; i < al->size; i++) {
325 alp = al->list + i;
326 rpmalAddProvides(al, i, alp->provides);
327 }
328}
329
330static void rpmalMakeObsoletesIndex(rpmal al)
331{
332 availablePackage alp;
333 int i, obsoletesCnt = 0;
334
335 for (i = 0; i < al->size; i++) {
336 alp = al->list + i;
337 obsoletesCnt += rpmdsCount(alp->obsoletes);
338 }
339
340 al->obsoletesHash = rpmalDepHashCreate(obsoletesCnt/4+128,
341 sidHash, sidCmp, NULL((void*)0), NULL((void*)0));
342 for (i = 0; i < al->size; i++) {
343 alp = al->list + i;
344 rpmalAddObsoletes(al, i, alp->obsoletes);
345 }
346}
347
348rpmte * rpmalAllObsoletes(rpmal al, rpmds ds)
349{
350 rpmte * ret = NULL((void*)0);
351 rpmsid nameId;
352 availableIndexEntry result;
353 int resultCnt;
354
355 if (al == NULL((void*)0) || ds == NULL((void*)0) || (nameId = rpmdsNId(ds)) == 0)
356 return ret;
357
358 if (al->obsoletesHash == NULL((void*)0))
359 rpmalMakeObsoletesIndex(al);
360
361 rpmalDepHashGetEntry(al->obsoletesHash, nameId, &result, &resultCnt, NULL((void*)0));
362
363 if (resultCnt > 0) {
364 availablePackage alp;
365 int rc, found = 0;
366
367 ret = xmalloc((resultCnt+1) * sizeof(*ret))rmalloc(((resultCnt+1) * sizeof(*ret)));
368
369 for (int i = 0; i < resultCnt; i++) {
370 alp = al->list + result[i].pkgNum;
371 if (alp->p == NULL((void*)0)) // deleted
372 continue;
373
374 rc = rpmdsCompareIndex(alp->obsoletes, result[i].entryIx,
375 ds, rpmdsIx(ds));
376
377 if (rc) {
378 rpmdsNotify(ds, "(added obsolete)", 0);
379 ret[found] = alp->p;
380 found++;
381 }
382 }
383
384 if (found)
385 ret[found] = NULL((void*)0);
386 else
387 ret = _free(ret)rfree((ret));
388 }
389
390 return ret;
391}
392
393static rpmte * rpmalAllFileSatisfiesDepend(const rpmal al, const char *fileName, const rpmds filterds)
394{
395 const char *slash;
396 rpmte * ret = NULL((void*)0);
397
398 if (al == NULL((void*)0) || fileName == NULL((void*)0) || *fileName != '/')
399 return NULL((void*)0);
400
401 /* Split path into dirname and basename components for lookup */
402 if ((slash = strrchr(fileName, '/')) != NULL((void*)0)) {
403 availableIndexFileEntry result;
404 int resultCnt = 0;
405 size_t bnStart = (slash - fileName) + 1;
406 rpmsid baseName;
407
408 if (al->fileHash == NULL((void*)0))
409 rpmalMakeFileIndex(al);
410
411 baseName = rpmstrPoolId(al->pool, fileName + bnStart, 0);
412 if (!baseName)
413 return NULL((void*)0); /* no match possible */
414
415 rpmalFileHashGetEntry(al->fileHash, baseName, &result, &resultCnt, NULL((void*)0));
416
417 if (resultCnt > 0) {
418 int i, found;
419 ret = xmalloc((resultCnt+1) * sizeof(*ret))rmalloc(((resultCnt+1) * sizeof(*ret)));
420 fingerPrint * fp = NULL((void*)0);
421 rpmsid dirName = rpmstrPoolIdn(al->pool, fileName, bnStart, 1);
422
423 if (!al->fpc)
424 al->fpc = fpCacheCreate(1001, NULL((void*)0));
425 fpLookup(al->fpc, rpmstrPoolStr(al->pool, dirName), fileName + bnStart, &fp);
426
427 for (found = i = 0; i < resultCnt; i++) {
428 availablePackage alp = al->list + result[i].pkgNum;
429 if (alp->p == NULL((void*)0)) /* deleted */
430 continue;
431 /* ignore self-conflicts/obsoletes */
432 if (filterds && rpmteDS(alp->p, rpmdsTagN(filterds)) == filterds)
433 continue;
434 if (result[i].dirName != dirName &&
435 !fpLookupEquals(al->fpc, fp, rpmstrPoolStr(al->pool, result[i].dirName), fileName + bnStart))
436 continue;
437
438 ret[found] = alp->p;
439 found++;
440 }
441 _free(fp)rfree((fp));
442 ret[found] = NULL((void*)0);
443 }
444 }
445
446 return ret;
447}
448
449rpmte * rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds)
450{
451 rpmte * ret = NULL((void*)0);
452 int i, ix, found;
453 rpmsid nameId;
454 const char *name;
455 availableIndexEntry result;
456 int resultCnt;
457 int obsolete;
458 rpmTagVal dtag;
459 rpmds filterds = NULL((void*)0);
460
461 availablePackage alp;
462 int rc;
463
464 if (al == NULL((void*)0) || ds == NULL((void*)0) || (nameId = rpmdsNId(ds)) == 0)
465 return ret;
466
467 dtag = rpmdsTagN(ds);
468 obsolete = (dtag == RPMTAG_OBSOLETENAME);
469 if (dtag == RPMTAG_OBSOLETENAME || dtag == RPMTAG_CONFLICTNAME)
470 filterds = ds;
471 name = rpmstrPoolStr(al->pool, nameId);
472 if (!obsolete && *name == '/') {
473 /* First, look for files "contained" in package ... */
474 ret = rpmalAllFileSatisfiesDepend(al, name, filterds);
475 if (ret != NULL((void*)0) && *ret != NULL((void*)0)) {
476 rpmdsNotify(ds, "(added files)", 0);
477 return ret;
478 }
479 /* ... then, look for files "provided" by package. */
480 ret = _free(ret)rfree((ret));
Value stored to 'ret' is never read
481 }
482
483 if (al->providesHash == NULL((void*)0))
484 rpmalMakeProvidesIndex(al);
485
486 rpmalDepHashGetEntry(al->providesHash, nameId, &result,
487 &resultCnt, NULL((void*)0));
488
489 if (resultCnt==0) return NULL((void*)0);
490
491 ret = xmalloc((resultCnt+1) * sizeof(*ret))rmalloc(((resultCnt+1) * sizeof(*ret)));
492
493 for (found=i=0; i<resultCnt; i++) {
494 alp = al->list + result[i].pkgNum;
495 if (alp->p == NULL((void*)0)) /* deleted */
496 continue;
497 /* ignore self-conflicts/obsoletes */
498 if (filterds && rpmteDS(alp->p, rpmdsTagN(filterds)) == filterds)
499 continue;
500 ix = result[i].entryIx;
501
502 if (obsolete) {
503 /* Obsoletes are on package NEVR only */
504 rpmds thisds;
505 if (!rstreq(rpmdsNIndex(alp->provides, ix), rpmteN(alp->p)))
506 continue;
507 thisds = rpmteDS(alp->p, RPMTAG_NAME);
508 rc = rpmdsCompareIndex(thisds, rpmdsIx(thisds), ds, rpmdsIx(ds));
509 } else {
510 rc = rpmdsCompareIndex(alp->provides, ix, ds, rpmdsIx(ds));
511 }
512
513 if (rc)
514 ret[found++] = alp->p;
515 }
516
517 if (found) {
518 rpmdsNotify(ds, "(added provide)", 0);
519 ret[found] = NULL((void*)0);
520 } else {
521 ret = _free(ret)rfree((ret));
522 }
523
524 return ret;
525}
526
527rpmte
528rpmalSatisfiesDepend(const rpmal al, const rpmte te, const rpmds ds)
529{
530 rpmte *providers = rpmalAllSatisfiesDepend(al, ds);
531 rpmte best = NULL((void*)0);
532 int bestscore = 0;
533
534 if (providers) {
535 rpm_color_t dscolor = rpmdsColor(ds);
536 for (rpmte *p = providers; *p; p++) {
537 int score = 0;
538
539 /*
540 * For colored dependencies, prefer a matching colored provider.
541 * Otherwise prefer provider of ts preferred color.
542 */
543 if (al->tscolor) {
544 rpm_color_t tecolor = rpmteColor(*p);
545 if (dscolor) {
546 if (dscolor == tecolor) score += 2;
547 } else if (al->prefcolor) {
548 if (al->prefcolor == tecolor) score += 2;
549 }
550 }
551
552 /* Being self-provided is a bonus */
553 if (*p == te)
554 score += 1;
555
556 if (score > bestscore) {
557 bestscore = score;
558 best = *p;
559 }
560 }
561 /* if not decided by now, just pick first match */
562 if (!best) best = providers[0];
563 free(providers);
564 }
565 return best;
566}