|
rpm
5.4.4
|
00001 00005 #include "system.h" 00006 00007 #include <rpmio.h> 00008 #include <rpmiotypes.h> /* XXX fnpyKey */ 00009 #include <rpmbf.h> 00010 00011 #include <rpmtag.h> 00012 #include <rpmtypes.h> 00013 00014 #define _RPMDS_INTERNAL 00015 #include <rpmds.h> 00016 #include <rpmal.h> 00017 00018 #include "debug.h" 00019 00020 typedef /*@abstract@*/ struct availablePackage_s * availablePackage; 00021 00022 /*@access alKey @*/ 00023 /*@access alNum @*/ 00024 /*@access rpmal @*/ 00025 /*@access rpmds @*/ 00026 /*@access availablePackage @*/ 00027 00028 /*@access fnpyKey @*/ /* XXX suggestedKeys array */ 00029 00030 /*@unchecked@*/ 00031 int _rpmal_debug = 0; 00032 00036 struct availablePackage_s { 00037 /*@refcounted@*/ /*@null@*/ 00038 rpmds provides; 00039 /*@refcounted@*/ /*@null@*/ 00040 rpmbf bf; 00042 rpmuint32_t tscolor; 00044 /*@exposed@*/ /*@dependent@*/ /*@null@*/ 00045 fnpyKey key; 00047 }; 00048 00049 typedef /*@abstract@*/ struct availableIndexEntry_s * availableIndexEntry; 00050 /*@access availableIndexEntry@*/ 00051 00055 struct availableIndexEntry_s { 00056 /*@exposed@*/ /*@dependent@*/ /*@null@*/ 00057 alKey pkgKey; 00058 /*@observer@*/ 00059 const char * entry; 00060 unsigned short entryLen; 00061 unsigned short entryIx; 00062 enum indexEntryType { 00063 IET_PROVIDES=1 00064 } type; 00065 }; 00066 00067 typedef /*@abstract@*/ struct availableIndex_s * availableIndex; 00068 /*@access availableIndex@*/ 00069 00073 struct availableIndex_s { 00074 /*@null@*/ 00075 availableIndexEntry index; 00076 int size; 00077 int k; 00078 }; 00079 00083 struct rpmal_s { 00084 struct rpmioItem_s _item; 00085 /*@owned@*/ /*@null@*/ 00086 availablePackage list; 00087 struct availableIndex_s index; 00088 int delta; 00089 int size; 00090 int alloced; 00091 rpmuint32_t tscolor; 00092 }; 00093 00094 static inline alNum alKey2Num(/*@unused@*/ /*@null@*/ const rpmal al, 00095 /*@null@*/ alKey pkgKey) 00096 /*@*/ 00097 { 00098 /*@-nullret -temptrans -retalias @*/ 00099 union { alKey key; alNum num; } u; 00100 u.num = 0; 00101 u.key = pkgKey; 00102 return u.num; 00103 /*@=nullret =temptrans =retalias @*/ 00104 } 00105 00106 static inline alKey alNum2Key(/*@unused@*/ /*@null@*/ const rpmal al, 00107 /*@null@*/ alNum pkgNum) 00108 /*@*/ 00109 { 00110 /*@-nullret -temptrans -retalias @*/ 00111 union { alKey key; alNum num; } u; 00112 u.key = 0; 00113 u.num = pkgNum; 00114 return u.key; 00115 /*@=nullret =temptrans =retalias @*/ 00116 } 00117 00122 static void rpmalFreeIndex(rpmal al) 00123 /*@modifies al @*/ 00124 { 00125 availableIndex ai = &al->index; 00126 if (ai->size > 0) { 00127 ai->index = _free(ai->index); 00128 ai->size = 0; 00129 } 00130 } 00131 00132 static void rpmalFini(void * _al) 00133 { 00134 rpmal al = _al; 00135 availablePackage alp; 00136 int i; 00137 00138 if ((alp = al->list) != NULL) 00139 for (i = 0; i < al->size; i++, alp++) { 00140 (void)rpmdsFree(alp->provides); 00141 alp->provides = NULL; 00142 (void)rpmbfFree(alp->bf); 00143 alp->bf = NULL; 00144 } 00145 00146 al->list = _free(al->list); 00147 al->alloced = 0; 00148 rpmalFreeIndex(al); 00149 } 00150 00151 /*@unchecked@*/ /*@only@*/ /*@null@*/ 00152 rpmioPool _rpmalPool; 00153 00154 static rpmal rpmalGetPool(/*@null@*/ rpmioPool pool) 00155 /*@globals _rpmdsPool, fileSystem, internalState @*/ 00156 /*@modifies pool, _rpmdsPool, fileSystem, internalState @*/ 00157 { 00158 rpmal al; 00159 00160 if (_rpmalPool == NULL) { 00161 _rpmalPool = rpmioNewPool("al", sizeof(*al), -1, _rpmal_debug, 00162 NULL, NULL, rpmalFini); 00163 pool = _rpmalPool; 00164 } 00165 al = (rpmal) rpmioGetPool(pool, sizeof(*al)); 00166 memset(((char *)al)+sizeof(al->_item), 0, sizeof(*al)-sizeof(al->_item)); 00167 return al; 00168 } 00169 00170 rpmal rpmalNew(int delta) 00171 { 00172 rpmal al = rpmalGetPool(_rpmalPool); 00173 availableIndex ai = &al->index; 00174 00175 al->delta = delta; 00176 al->size = 0; 00177 al->list = xcalloc(al->delta, sizeof(*al->list)); 00178 al->alloced = al->delta; 00179 00180 ai->index = NULL; 00181 ai->size = 0; 00182 00183 return rpmalLink(al, __FUNCTION__); 00184 } 00185 00186 void rpmalDel(rpmal al, alKey pkgKey) 00187 { 00188 alNum pkgNum = alKey2Num(al, pkgKey); 00189 availablePackage alp; 00190 00191 if (al == NULL || al->list == NULL) 00192 return; /* XXX can't happen */ 00193 00194 alp = al->list + pkgNum; 00195 00196 (void)rpmdsFree(alp->provides); 00197 alp->provides = NULL; 00198 (void)rpmbfFree(alp->bf); 00199 alp->bf = NULL; 00200 00201 memset(alp, 0, sizeof(*alp)); /* XXX trash and burn */ 00202 return; 00203 } 00204 00205 alKey rpmalAdd(rpmal * alistp, alKey pkgKey, fnpyKey key, 00206 rpmds provides, rpmfi fi, rpmuint32_t tscolor) 00207 { 00208 alNum pkgNum; 00209 rpmal al; 00210 availablePackage alp; 00211 00212 /* If list doesn't exist yet, create. */ 00213 if (*alistp == NULL) 00214 *alistp = rpmalNew(5); 00215 al = *alistp; 00216 pkgNum = alKey2Num(al, pkgKey); 00217 00218 if (pkgNum >= 0 && pkgNum < al->size) { 00219 rpmalDel(al, pkgKey); 00220 } else { 00221 if (al->size == al->alloced) { 00222 al->alloced += al->delta; 00223 al->list = xrealloc(al->list, sizeof(*al->list) * al->alloced); 00224 } 00225 pkgNum = al->size++; 00226 } 00227 00228 if (al->list == NULL) 00229 return RPMAL_NOMATCH; /* XXX can't happen */ 00230 00231 alp = al->list + pkgNum; 00232 00233 alp->key = key; 00234 alp->tscolor = tscolor; 00235 00236 /*@-assignexpose -castexpose @*/ 00237 alp->provides = rpmdsLink(provides, "Provides (rpmalAdd)"); 00238 alp->bf = rpmbfLink(rpmfiFNBF(fi)); 00239 /*@=assignexpose =castexpose @*/ 00240 00241 rpmalFreeIndex(al); 00242 00243 assert(((alNum)(alp - al->list)) == pkgNum); 00244 return ((alKey)(alp - al->list)); 00245 } 00246 00253 static int indexcmp(const void * one, const void * two) 00254 /*@*/ 00255 { 00256 /*@-castexpose@*/ 00257 const availableIndexEntry a = (const availableIndexEntry) one; 00258 const availableIndexEntry b = (const availableIndexEntry) two; 00259 /*@=castexpose@*/ 00260 int lenchk; 00261 00262 lenchk = a->entryLen - b->entryLen; 00263 if (lenchk) 00264 return lenchk; 00265 00266 return strcmp(a->entry, b->entry); 00267 } 00268 00269 void rpmalAddProvides(rpmal al, alKey pkgKey, rpmds provides, rpmuint32_t tscolor) 00270 { 00271 rpmuint32_t dscolor; 00272 const char * Name; 00273 alNum pkgNum = alKey2Num(al, pkgKey); 00274 availableIndex ai = &al->index; 00275 availableIndexEntry aie; 00276 int ix; 00277 00278 if (provides == NULL || pkgNum < 0 || pkgNum >= al->size) 00279 return; 00280 if (ai->index == NULL || ai->k < 0 || ai->k >= ai->size) 00281 return; 00282 00283 if (rpmdsInit(provides) != NULL) 00284 while (rpmdsNext(provides) >= 0) { 00285 00286 if ((Name = provides->N[provides->i]) == NULL) 00287 continue; /* XXX can't happen */ 00288 00289 /* Ignore colored provides not in our rainbow. */ 00290 dscolor = rpmdsColor(provides); 00291 if (tscolor && dscolor && !(tscolor & dscolor)) 00292 continue; 00293 00294 aie = ai->index + ai->k; 00295 ai->k++; 00296 00297 aie->pkgKey = pkgKey; 00298 /*@-assignexpose@*/ 00299 aie->entry = Name; 00300 /*@=assignexpose@*/ 00301 aie->entryLen = (unsigned short)strlen(Name); 00302 ix = rpmdsIx(provides); 00303 00304 /* XXX make sure that element index fits in unsigned short */ 00305 assert(ix < 0x10000); 00306 00307 aie->entryIx = ix; 00308 aie->type = IET_PROVIDES; 00309 } 00310 } 00311 00312 void rpmalMakeIndex(rpmal al) 00313 { 00314 availableIndex ai; 00315 availablePackage alp; 00316 int i; 00317 00318 if (al == NULL || al->list == NULL) return; 00319 ai = &al->index; 00320 00321 ai->size = 0; 00322 for (i = 0; i < al->size; i++) { 00323 alp = al->list + i; 00324 if (alp->provides != NULL) 00325 ai->size += rpmdsCount(alp->provides); 00326 } 00327 if (ai->size == 0) return; 00328 00329 ai->index = xrealloc(ai->index, ai->size * sizeof(*ai->index)); 00330 ai->k = 0; 00331 for (i = 0; i < al->size; i++) { 00332 alp = al->list + i; 00333 rpmalAddProvides(al, alNum2Key(NULL, (alNum)i), alp->provides, alp->tscolor); 00334 } 00335 00336 /* Reset size to the no. of provides added. */ 00337 ai->size = ai->k; 00338 qsort(ai->index, ai->size, sizeof(*ai->index), indexcmp); 00339 } 00340 00341 fnpyKey * 00342 rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp) 00343 { 00344 fnpyKey * ret = NULL; 00345 int found = 0; 00346 const char * fn; 00347 size_t nfn; 00348 int i; 00349 00350 if (keyp) *keyp = RPMAL_NOMATCH; 00351 00352 if (al == NULL || (fn = rpmdsN(ds)) == NULL || *fn != '/') 00353 goto exit; 00354 nfn = strlen(fn); 00355 00356 if (al->list != NULL) /* XXX always true */ 00357 for (i = 0; i < al->size; i++) { 00358 availablePackage alp = al->list + i; 00359 00360 if (!rpmbfChk(alp->bf, fn, nfn)) 00361 continue; 00362 00363 rpmdsNotify(ds, _("(added files)"), 0); 00364 00365 ret = xrealloc(ret, (found + 2) * sizeof(*ret)); 00366 if (ret) /* can't happen */ 00367 ret[found] = alp->key; 00368 if (keyp) 00369 *keyp = alNum2Key(al, i); 00370 found++; 00371 } 00372 00373 if (ret) 00374 ret[found] = NULL; 00375 00376 exit: 00377 /*@-nullstate@*/ /* FIX: *keyp may be NULL */ 00378 return ret; 00379 /*@=nullstate@*/ 00380 } 00381 00382 fnpyKey * 00383 rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp) 00384 { 00385 availableIndex ai; 00386 availableIndexEntry needle; 00387 availableIndexEntry match; 00388 fnpyKey * ret = NULL; 00389 int found = 0; 00390 const char * KName; 00391 availablePackage alp; 00392 int rc; 00393 00394 if (keyp) *keyp = RPMAL_NOMATCH; 00395 00396 if (al == NULL || ds == NULL || (KName = rpmdsN(ds)) == NULL) 00397 goto exit; 00398 00399 if (*KName == '/') { 00400 /* First, look for files "contained" in package ... */ 00401 ret = rpmalAllFileSatisfiesDepend(al, ds, keyp); 00402 if (ret != NULL && *ret != NULL) 00403 goto exit; 00404 ret = _free(ret); 00405 /* ... then, look for files "provided" by package. */ 00406 } 00407 00408 ai = &al->index; 00409 if (ai->index == NULL || ai->size <= 0) 00410 goto exit; 00411 00412 needle = memset(alloca(sizeof(*needle)), 0, sizeof(*needle)); 00413 /*@-assignexpose -temptrans@*/ 00414 needle->entry = KName; 00415 /*@=assignexpose =temptrans@*/ 00416 needle->entryLen = (unsigned short)strlen(needle->entry); 00417 00418 match = bsearch(needle, ai->index, ai->size, sizeof(*ai->index), indexcmp); 00419 if (match == NULL) 00420 goto exit; 00421 00422 /* rewind to the first match */ 00423 while (match > ai->index && indexcmp(match-1, needle) == 0) 00424 match--; 00425 00426 if (al->list != NULL) /* XXX always true */ 00427 for (ret = NULL, found = 0; 00428 match < ai->index + ai->size && indexcmp(match, needle) == 0; 00429 match++) 00430 { 00431 alp = al->list + alKey2Num(al, match->pkgKey); 00432 00433 rc = 0; 00434 if (alp->provides != NULL) /* XXX can't happen */ 00435 switch (match->type) { 00436 case IET_PROVIDES: 00437 /* XXX single step on rpmdsNext to regenerate DNEVR string */ 00438 (void) rpmdsSetIx(alp->provides, match->entryIx - 1); 00439 if (rpmdsNext(alp->provides) >= 0) 00440 rc = rpmdsCompare(alp->provides, ds); 00441 00442 if (rc) 00443 rpmdsNotify(ds, _("(added provide)"), 0); 00444 00445 /*@switchbreak@*/ break; 00446 } 00447 00448 if (rc) { 00449 ret = xrealloc(ret, (found + 2) * sizeof(*ret)); 00450 if (ret) /* can't happen */ 00451 ret[found] = alp->key; 00452 /*@-dependenttrans@*/ 00453 if (keyp) 00454 *keyp = match->pkgKey; 00455 /*@=dependenttrans@*/ 00456 found++; 00457 } 00458 } 00459 00460 if (ret) 00461 ret[found] = NULL; 00462 00463 exit: 00464 /*@-nullstate@*/ /* FIX: *keyp may be NULL */ 00465 return ret; 00466 /*@=nullstate@*/ 00467 } 00468 00469 fnpyKey 00470 rpmalSatisfiesDepend(const rpmal al, const rpmds ds, alKey * keyp) 00471 { 00472 fnpyKey * tmp = rpmalAllSatisfiesDepend(al, ds, keyp); 00473 00474 if (tmp) { 00475 fnpyKey ret = tmp[0]; 00476 free(tmp); 00477 return ret; 00478 } 00479 return NULL; 00480 }
1.7.5.1