summaryrefslogtreecommitdiff
path: root/lib/lookup.c
blob: a53cb946fa9d8ff216ebd5e654da0127f35ad650 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#include "system.h"

#include "rpmlib.h"

static int findMatches(rpmdb db, char * name, char * version, char * release,
		       dbiIndexSet * matches);

/* 0 found matches */
/* 1 no matches */
/* 2 error */
int rpmdbFindByHeader(rpmdb db, Header h, dbiIndexSet * matches) {
    char * name, * version, * release;

    headerGetEntry(h, RPMTAG_NAME, NULL, (void **) &name, NULL);
    headerGetEntry(h, RPMTAG_VERSION, NULL, (void **) &version, NULL);
    headerGetEntry(h, RPMTAG_RELEASE, NULL, (void **) &release, NULL);

    return findMatches(db, name, version, release, matches);
}

/* 0 found matches */
/* 1 no matches */
/* 2 error */
int rpmdbFindByLabel(rpmdb db, char * arg, dbiIndexSet * matches) {
    char * localarg, * chptr;
    char * release;
    int rc;
 
    if (!strlen(arg)) return 1;

    /* did they give us just a name? */
    rc = findMatches(db, arg, NULL, NULL, matches);
    if (rc != 1) return rc;

    /* maybe a name and a release */
    localarg = alloca(strlen(arg) + 1);
    strcpy(localarg, arg);

    chptr = (localarg + strlen(localarg)) - 1;
    while (chptr > localarg && *chptr != '-') chptr--;
    if (chptr == localarg) return 1;

    *chptr = '\0';
    rc = findMatches(db, localarg, chptr + 1, NULL, matches);
    if (rc != 1) return rc;
    
    /* how about name-version-release? */

    release = chptr + 1;
    while (chptr > localarg && *chptr != '-') chptr--;
    if (chptr == localarg) return 1;

    *chptr = '\0';
    return findMatches(db, localarg, chptr + 1, release, matches);
}

/* 0 found matches */
/* 1 no matches */
/* 2 error */
static int findMatches(rpmdb db, char * name, char * version, char * release,
		       dbiIndexSet * matches) {
    int gotMatches;
    int rc;
    int i;
    char * pkgRelease, * pkgVersion;
    int count, type;
    int goodRelease, goodVersion;
    Header h;

    if ((rc = rpmdbFindPackage(db, name, matches))) {
	if (rc == -1) return 2; else return 1;
    }

    if (!version && !release) return 0;

    gotMatches = 0;

    /* make sure the version and releases match */
    for (i = 0; i < matches->count; i++) {
	if (matches->recs[i].recOffset) {
	    h = rpmdbGetRecord(db, matches->recs[i].recOffset);
	    if (!h) {
		rpmError(RPMERR_DBCORRUPT, 
			 _("cannot read header at %d for lookup"), 
			matches->recs[i].recOffset);
		dbiFreeIndexRecord(*matches);
		return 2;
	    }

	    headerGetEntry(h, RPMTAG_VERSION, &type, (void **) &pkgVersion, 
			   &count);
	    headerGetEntry(h, RPMTAG_RELEASE, &type, (void **) &pkgRelease, 
			   &count);
	    
	    goodRelease = goodVersion = 1;

	    if (release && strcmp(release, pkgRelease)) goodRelease = 0;
	    if (version && strcmp(version, pkgVersion)) goodVersion = 0;

	    if (goodRelease && goodVersion) 
		gotMatches = 1;
	    else 
		matches->recs[i].recOffset = 0;

	    headerFree(h);
	}
    }

    if (!gotMatches) {
	dbiFreeIndexRecord(*matches);
	return 1;
    }
    
    return 0;
}