~ubuntu-branches/debian/sid/rpm/sid

« back to all changes in this revision

Viewing changes to lib/rpmal.c

  • Committer: Package Import Robot
  • Author(s): Michal Čihař
  • Date: 2013-06-06 11:39:34 UTC
  • mfrom: (1.1.16)
  • Revision ID: package-import@ubuntu.com-20130606113934-ela3du14fyba0t6u
Tags: 4.11.0.1-1
* New upstream release.
* Bump standards to 3.9.4.
* Refresh patches, update patch from Fedora.
* Build with Lua 5.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
5
5
#include "system.h"
6
6
 
7
7
 
8
 
#include <rpm/rpmds.h>
9
8
#include <rpm/rpmte.h>
10
9
#include <rpm/rpmfi.h>
 
10
#include <rpm/rpmstrpool.h>
11
11
 
12
12
#include "lib/rpmal.h"
13
13
#include "lib/misc.h"
14
14
#include "lib/rpmte_internal.h"
 
15
#include "lib/rpmds_internal.h"
 
16
#include "lib/rpmfi_internal.h"
15
17
 
16
18
#include "debug.h"
17
19
 
24
26
struct availablePackage_s {
25
27
    rpmte p;                    /*!< transaction member */
26
28
    rpmds provides;             /*!< Provides: dependencies. */
 
29
    rpmds obsoletes;            /*!< Obsoletes: dependencies. */
27
30
    rpmfi fi;                   /*!< File info set. */
28
31
};
29
32
 
36
39
} * availableIndexEntry;
37
40
 
38
41
struct fileNameEntry_s {
39
 
    const char * dirName;
40
 
    const char * baseName;
 
42
    rpmsid dirName;
 
43
    rpmsid baseName;
41
44
};
42
45
 
43
46
#undef HASHTYPE
44
47
#undef HTKEYTYPE
45
48
#undef HTDATATYPE
46
 
#define HASHTYPE rpmalProvidesHash
47
 
#define HTKEYTYPE const char *
 
49
#define HASHTYPE rpmalDepHash
 
50
#define HTKEYTYPE rpmsid
48
51
#define HTDATATYPE struct availableIndexEntry_s
49
52
#include "lib/rpmhash.H"
50
53
#include "lib/rpmhash.C"
62
65
 * Set of available packages, items, and directories.
63
66
 */
64
67
struct rpmal_s {
 
68
    rpmstrPool pool;            /*!< String pool */
65
69
    availablePackage list;      /*!< Set of packages. */
66
 
    rpmalProvidesHash providesHash;
 
70
    rpmalDepHash providesHash;
 
71
    rpmalDepHash obsoletesHash;
67
72
    rpmalFileHash fileHash;
68
73
    int delta;                  /*!< Delta for pkg list reallocation. */
69
74
    int size;                   /*!< No. of pkgs in list. */
79
84
 */
80
85
static void rpmalFreeIndex(rpmal al)
81
86
{
82
 
    al->providesHash = rpmalProvidesHashFree(al->providesHash);
 
87
    al->providesHash = rpmalDepHashFree(al->providesHash);
 
88
    al->obsoletesHash = rpmalDepHashFree(al->obsoletesHash);
83
89
    al->fileHash = rpmalFileHashFree(al->fileHash);
84
90
}
85
91
 
86
 
rpmal rpmalCreate(int delta, rpmtransFlags tsflags,
 
92
rpmal rpmalCreate(rpmstrPool pool, int delta, rpmtransFlags tsflags,
87
93
                  rpm_color_t tscolor, rpm_color_t prefcolor)
88
94
{
89
95
    rpmal al = xcalloc(1, sizeof(*al));
90
96
 
 
97
    /* transition time safe-guard */
 
98
    assert(pool != NULL);
 
99
 
 
100
    al->pool = rpmstrPoolLink(pool);
91
101
    al->delta = delta;
92
102
    al->size = 0;
93
103
    al->alloced = al->delta;
94
104
    al->list = xmalloc(sizeof(*al->list) * al->alloced);;
95
105
 
96
106
    al->providesHash = NULL;
 
107
    al->obsoletesHash = NULL;
97
108
    al->fileHash = NULL;
98
109
    al->tsflags = tsflags;
99
110
    al->tscolor = tscolor;
112
123
 
113
124
    if ((alp = al->list) != NULL)
114
125
    for (i = 0; i < al->size; i++, alp++) {
 
126
        alp->obsoletes = rpmdsFree(alp->obsoletes);
115
127
        alp->provides = rpmdsFree(alp->provides);
116
128
        alp->fi = rpmfiFree(alp->fi);
117
129
    }
 
130
    al->pool = rpmstrPoolFree(al->pool);
118
131
    al->list = _free(al->list);
119
132
    al->alloced = 0;
120
133
 
123
136
    return NULL;
124
137
}
125
138
 
 
139
static unsigned int sidHash(rpmsid sid)
 
140
{
 
141
    return sid;
 
142
}
 
143
 
 
144
static int sidCmp(rpmsid a, rpmsid b)
 
145
{
 
146
    return (a != b);
 
147
}
 
148
 
126
149
static unsigned int fileHash(struct fileNameEntry_s file)
127
150
{
128
 
    return rstrhash(file.dirName) ^ rstrhash(file.baseName);
 
151
    return file.dirName ^ file.baseName;
129
152
}
130
153
 
131
154
static int fileCompare(struct fileNameEntry_s one, struct fileNameEntry_s two)
132
155
{
133
 
    int rc = 0;
134
 
    rc = strcmp(one.dirName, two.dirName);
 
156
    int rc = (one.dirName != two.dirName);;
135
157
    if (!rc)
136
 
        rc = strcmp(one.baseName, two.baseName);
 
158
        rc = (one.baseName != two.baseName);
137
159
    return rc;
138
160
}
139
161
 
163
185
{
164
186
    struct fileNameEntry_s fileName;
165
187
    struct availableIndexEntry_s fileEntry;
166
 
    int i;
 
188
    int fc = rpmfiFC(fi);
167
189
    rpm_color_t ficolor;
168
190
    int skipdoc = (al->tsflags & RPMTRANS_FLAG_NODOCS);
169
191
    int skipconf = (al->tsflags & RPMTRANS_FLAG_NOCONFIGS);
170
192
 
171
193
    fileEntry.pkgNum = pkgNum;
172
194
 
173
 
    fi = rpmfiInit(fi, 0);
174
 
    while ((i = rpmfiNext(fi)) >= 0) {
 
195
    for (int i = 0; i < fc; i++) {
175
196
        /* Ignore colored provides not in our rainbow. */
176
 
        ficolor = rpmfiFColor(fi);
 
197
        ficolor = rpmfiFColorIndex(fi, i);
177
198
        if (al->tscolor && ficolor && !(al->tscolor & ficolor))
178
199
            continue;
179
200
 
180
201
        /* Ignore files that wont be installed */
181
 
        if (skipdoc && (rpmfiFFlags(fi) & RPMFILE_DOC))
 
202
        if (skipdoc && (rpmfiFFlagsIndex(fi, i) & RPMFILE_DOC))
182
203
            continue;
183
 
        if (skipconf && (rpmfiFFlags(fi) & RPMFILE_CONFIG))
 
204
        if (skipconf && (rpmfiFFlagsIndex(fi, i) & RPMFILE_CONFIG))
184
205
            continue;
185
206
 
186
 
        fileName.dirName = rpmfiDN(fi);
187
 
        fileName.baseName = rpmfiBN(fi);
 
207
        fileName.dirName = rpmfiDNIdIndex(fi, rpmfiDIIndex(fi, i));
 
208
        fileName.baseName = rpmfiBNIdIndex(fi, i);
188
209
 
189
210
        fileEntry.entryIx = i;
190
211
 
197
218
    struct availableIndexEntry_s indexEntry;
198
219
    rpm_color_t dscolor;
199
220
    int skipconf = (al->tsflags & RPMTRANS_FLAG_NOCONFIGS);
 
221
    int dc = rpmdsCount(provides);
200
222
 
201
223
    indexEntry.pkgNum = pkgNum;
202
224
 
203
 
    if (rpmdsInit(provides) != NULL)
204
 
    while (rpmdsNext(provides) >= 0) {
 
225
    for (int i = 0; i < dc; i++) {
205
226
        /* Ignore colored provides not in our rainbow. */
206
 
        dscolor = rpmdsColor(provides);
 
227
        dscolor = rpmdsColorIndex(provides, i);
207
228
        if (al->tscolor && dscolor && !(al->tscolor & dscolor))
208
229
            continue;
209
230
 
210
231
        /* Ignore config() provides if the files wont be installed */
211
 
        if (skipconf & (rpmdsFlags(provides) & RPMSENSE_CONFIG))
 
232
        if (skipconf & (rpmdsFlagsIndex(provides, i) & RPMSENSE_CONFIG))
212
233
            continue;
213
234
 
214
 
        indexEntry.entryIx = rpmdsIx(provides);
215
 
        rpmalProvidesHashAddEntry(al->providesHash, rpmdsN(provides), indexEntry);
 
235
        indexEntry.entryIx = i;;
 
236
        rpmalDepHashAddEntry(al->providesHash,
 
237
                                  rpmdsNIdIndex(provides, i), indexEntry);
 
238
    }
 
239
}
 
240
 
 
241
static void rpmalAddObsoletes(rpmal al, rpmalNum pkgNum, rpmds obsoletes)
 
242
{
 
243
    struct availableIndexEntry_s indexEntry;
 
244
    rpm_color_t dscolor;
 
245
    int dc = rpmdsCount(obsoletes);
 
246
 
 
247
    indexEntry.pkgNum = pkgNum;
 
248
 
 
249
    for (int i = 0; i < dc; i++) {
 
250
        /* Obsoletes shouldn't be colored but just in case... */
 
251
        dscolor = rpmdsColorIndex(obsoletes, i);
 
252
        if (al->tscolor && dscolor && !(al->tscolor & dscolor))
 
253
            continue;
 
254
 
 
255
        indexEntry.entryIx = i;;
 
256
        rpmalDepHashAddEntry(al->obsoletesHash,
 
257
                                  rpmdsNIdIndex(obsoletes, i), indexEntry);
216
258
    }
217
259
}
218
260
 
232
274
    alp->p = p;
233
275
 
234
276
    alp->provides = rpmdsLink(rpmteDS(p, RPMTAG_PROVIDENAME));
 
277
    alp->obsoletes = rpmdsLink(rpmteDS(p, RPMTAG_OBSOLETENAME));
235
278
    alp->fi = rpmfiLink(rpmteFI(p));
236
279
 
237
 
    if (al->providesHash != NULL) { // index is already created
 
280
    /*
 
281
     * Transition-time safe-guard to catch private-pool uses.
 
282
     * File sets with no files have NULL pool, that's fine. But WTF is up
 
283
     * with the provides: every single package should have at least its
 
284
     * own name as a provide, and thus never NULL, and normal use matches
 
285
     * this expectation. However the test-suite is tripping up on NULL
 
286
     * NULL pool from NULL alp->provides in numerous cases?
 
287
     */
 
288
    {
 
289
        rpmstrPool fipool = rpmfiPool(alp->fi);
 
290
        rpmstrPool dspool = rpmdsPool(alp->provides);
 
291
        
 
292
        assert(fipool == NULL || fipool == al->pool);
 
293
        assert(dspool == NULL || dspool == al->pool);
 
294
    }
 
295
 
 
296
    /* Try to be lazy as delayed hash creation is cheaper */
 
297
    if (al->providesHash != NULL)
238
298
        rpmalAddProvides(al, pkgNum, alp->provides);
 
299
    if (al->obsoletesHash != NULL)
 
300
        rpmalAddObsoletes(al, pkgNum, alp->obsoletes);
 
301
    if (al->fileHash != NULL)
239
302
        rpmalAddFiles(al, pkgNum, alp->fi);
240
 
    }
241
303
 
242
304
    assert(((rpmalNum)(alp - al->list)) == pkgNum);
243
305
}
244
306
 
245
 
static void rpmalMakeIndex(rpmal al)
 
307
static void rpmalMakeFileIndex(rpmal al)
246
308
{
247
309
    availablePackage alp;
248
 
    int i;
249
 
    int providesCnt = 0;
250
 
    int fileCnt = 0;
 
310
    int i, fileCnt = 0;
251
311
 
252
 
    if (al == NULL || al->list == NULL) return;
253
 
    if (al->providesHash != NULL || al->fileHash != NULL)
254
 
        return;
255
312
    for (i = 0; i < al->size; i++) {
256
313
        alp = al->list + i;
257
 
        if (alp->provides != NULL)
258
 
            providesCnt += rpmdsCount(alp->provides);
259
314
        if (alp->fi != NULL)
260
315
            fileCnt += rpmfiFC(alp->fi);
261
316
    }
262
 
 
263
 
    al->providesHash = rpmalProvidesHashCreate(providesCnt/4+128, rstrhash,
264
 
                                               strcmp, NULL, NULL);
265
 
    al->fileHash = rpmalFileHashCreate(fileCnt/4+128, fileHash, fileCompare,
266
 
                                       NULL, NULL);
267
 
 
 
317
    al->fileHash = rpmalFileHashCreate(fileCnt/4+128,
 
318
                                       fileHash, fileCompare, NULL, NULL);
 
319
    for (i = 0; i < al->size; i++) {
 
320
        alp = al->list + i;
 
321
        rpmalAddFiles(al, i, alp->fi);
 
322
    }
 
323
}
 
324
 
 
325
static void rpmalMakeProvidesIndex(rpmal al)
 
326
{
 
327
    availablePackage alp;
 
328
    int i, providesCnt = 0;
 
329
 
 
330
    for (i = 0; i < al->size; i++) {
 
331
        alp = al->list + i;
 
332
        providesCnt += rpmdsCount(alp->provides);
 
333
    }
 
334
 
 
335
    al->providesHash = rpmalDepHashCreate(providesCnt/4+128,
 
336
                                               sidHash, sidCmp, NULL, NULL);
268
337
    for (i = 0; i < al->size; i++) {
269
338
        alp = al->list + i;
270
339
        rpmalAddProvides(al, i, alp->provides);
271
 
        rpmalAddFiles(al, i, alp->fi);
272
 
    }
273
 
}
274
 
 
275
 
static rpmte * rpmalAllFileSatisfiesDepend(const rpmal al, const rpmds ds)
276
 
{
277
 
    const char *fileName = rpmdsN(ds);
 
340
    }
 
341
}
 
342
 
 
343
static void rpmalMakeObsoletesIndex(rpmal al)
 
344
{
 
345
    availablePackage alp;
 
346
    int i, obsoletesCnt = 0;
 
347
 
 
348
    for (i = 0; i < al->size; i++) {
 
349
        alp = al->list + i;
 
350
        obsoletesCnt += rpmdsCount(alp->obsoletes);
 
351
    }
 
352
 
 
353
    al->obsoletesHash = rpmalDepHashCreate(obsoletesCnt/4+128,
 
354
                                               sidHash, sidCmp, NULL, NULL);
 
355
    for (i = 0; i < al->size; i++) {
 
356
        alp = al->list + i;
 
357
        rpmalAddObsoletes(al, i, alp->obsoletes);
 
358
    }
 
359
}
 
360
 
 
361
rpmte * rpmalAllObsoletes(rpmal al, rpmds ds)
 
362
{
 
363
    rpmte * ret = NULL;
 
364
    rpmsid nameId;
 
365
    availableIndexEntry result;
 
366
    int resultCnt;
 
367
 
 
368
    if (al == NULL || ds == NULL || (nameId = rpmdsNId(ds)) == 0)
 
369
        return ret;
 
370
 
 
371
    if (al->obsoletesHash == NULL)
 
372
        rpmalMakeObsoletesIndex(al);
 
373
 
 
374
    rpmalDepHashGetEntry(al->obsoletesHash, nameId, &result, &resultCnt, NULL);
 
375
 
 
376
    if (resultCnt > 0) {
 
377
        availablePackage alp;
 
378
        int rc, found = 0;
 
379
 
 
380
        ret = xmalloc((resultCnt+1) * sizeof(*ret));
 
381
 
 
382
        for (int i = 0; i < resultCnt; i++) {
 
383
            alp = al->list + result[i].pkgNum;
 
384
            if (alp->p == NULL) // deleted
 
385
                continue;
 
386
 
 
387
            rc = rpmdsCompareIndex(alp->obsoletes, result[i].entryIx,
 
388
                                   ds, rpmdsIx(ds));
 
389
 
 
390
            if (rc) {
 
391
                rpmdsNotify(ds, "(added obsolete)", 0);
 
392
                ret[found] = alp->p;
 
393
                found++;
 
394
            }
 
395
        }
 
396
 
 
397
        if (found)
 
398
            ret[found] = NULL;
 
399
        else
 
400
            ret = _free(ret);
 
401
    }
 
402
 
 
403
    return ret;
 
404
}
 
405
 
 
406
static rpmte * rpmalAllFileSatisfiesDepend(const rpmal al, const char *fileName)
 
407
{
278
408
    const char *slash; 
279
409
    rpmte * ret = NULL;
280
410
 
286
416
        availableIndexEntry result;
287
417
        int resultCnt = 0;
288
418
        size_t bnStart = (slash - fileName) + 1;
289
 
        char dirName[bnStart + 1];
290
 
        struct fileNameEntry_s fne = {
291
 
            .baseName = fileName + bnStart,
292
 
            .dirName = dirName,
293
 
        };
294
 
        strncpy(dirName, fileName, bnStart);
295
 
        dirName[bnStart] = '\0';
 
419
        struct fileNameEntry_s fne;
 
420
 
 
421
        fne.baseName = rpmstrPoolId(al->pool, fileName + bnStart, 0);
 
422
        fne.dirName = rpmstrPoolIdn(al->pool, fileName, bnStart, 0);
 
423
 
 
424
        if (al->fileHash == NULL)
 
425
            rpmalMakeFileIndex(al);
296
426
 
297
427
        rpmalFileHashGetEntry(al->fileHash, fne, &result, &resultCnt, NULL);
298
428
 
305
435
                if (alp->p == NULL) // deleted
306
436
                    continue;
307
437
 
308
 
                rpmdsNotify(ds, "(added files)", 0);
309
 
 
310
438
                ret[found] = alp->p;
311
439
                found++;
312
440
            }
317
445
    return ret;
318
446
}
319
447
 
320
 
static rpmte * rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds)
 
448
rpmte * rpmalAllSatisfiesDepend(const rpmal al, const rpmds ds)
321
449
{
322
450
    rpmte * ret = NULL;
323
 
    int i, found;
324
 
    const char * name;
 
451
    int i, ix, found;
 
452
    rpmsid nameId;
 
453
    const char *name;
325
454
    availableIndexEntry result;
326
455
    int resultCnt;
327
456
    int obsolete;
329
458
    availablePackage alp;
330
459
    int rc;
331
460
 
332
 
    if (al == NULL || ds == NULL || (name = rpmdsN(ds)) == NULL)
 
461
    if (al == NULL || ds == NULL || (nameId = rpmdsNId(ds)) == 0)
333
462
        return ret;
334
463
 
335
 
    if (al->providesHash == NULL && al->fileHash == NULL)
336
 
        rpmalMakeIndex(al);
337
 
 
338
464
    obsolete = (rpmdsTagN(ds) == RPMTAG_OBSOLETENAME);
 
465
    name = rpmstrPoolStr(al->pool, nameId);
339
466
    if (!obsolete && *name == '/') {
340
467
        /* First, look for files "contained" in package ... */
341
 
        ret = rpmalAllFileSatisfiesDepend(al, ds);
342
 
        if (ret != NULL && *ret != NULL)
 
468
        ret = rpmalAllFileSatisfiesDepend(al, name);
 
469
        if (ret != NULL && *ret != NULL) {
 
470
            rpmdsNotify(ds, "(added files)", 0);
343
471
            return ret;
 
472
        }
344
473
        /* ... then, look for files "provided" by package. */
345
474
        ret = _free(ret);
346
475
    }
347
476
 
348
 
    rpmalProvidesHashGetEntry(al->providesHash, name, &result,
 
477
    if (al->providesHash == NULL)
 
478
        rpmalMakeProvidesIndex(al);
 
479
 
 
480
    rpmalDepHashGetEntry(al->providesHash, nameId, &result,
349
481
                              &resultCnt, NULL);
350
482
 
351
483
    if (resultCnt==0) return NULL;
356
488
        alp = al->list + result[i].pkgNum;
357
489
        if (alp->p == NULL) // deleted
358
490
            continue;
359
 
        (void) rpmdsSetIx(alp->provides, result[i].entryIx);
 
491
        ix = result[i].entryIx;
360
492
 
361
493
        /* Obsoletes are on package name, filter out other provide matches */
362
 
        if (obsolete && !rstreq(rpmdsN(alp->provides), rpmteN(alp->p)))
 
494
        if (obsolete && !rstreq(rpmdsNIndex(alp->provides, ix), rpmteN(alp->p)))
363
495
            continue;
364
496
 
365
 
        rc = 0;
366
 
        if (rpmdsIx(alp->provides) >= 0)
367
 
            rc = rpmdsCompare(alp->provides, ds);
 
497
        rc = rpmdsCompareIndex(alp->provides, ix, ds, rpmdsIx(ds));
368
498
 
369
499
        if (rc) {
370
500
            rpmdsNotify(ds, "(added provide)", 0);
372
502
            found++;
373
503
        }
374
504
    }
375
 
    ret[found] = NULL;
 
505
 
 
506
    if (found)
 
507
        ret[found] = NULL;
 
508
    else
 
509
        ret = _free(ret);
376
510
 
377
511
    return ret;
378
512
}