diff options
author | Patrick Williams <patrick@stwcx.xyz> | 2015-09-15 22:41:29 +0300 |
---|---|---|
committer | Patrick Williams <patrick@stwcx.xyz> | 2015-09-15 22:41:29 +0300 |
commit | 21f9b84b4b729fbd7acbd465e7a3f726e4d20f91 (patch) | |
tree | eb2d091d427ca0813b445509d59cc8e27e8ad25f /yocto-poky/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c | |
parent | 101cef31e2bf54c678501155cd2106251acbd076 (diff) | |
parent | c124f4f2e04dca16a428a76c89677328bc7bf908 (diff) | |
download | openbmc-21f9b84b4b729fbd7acbd465e7a3f726e4d20f91.tar.xz |
Merge commit 'c124f4f2e04dca16a428a76c89677328bc7bf908' as 'yocto-poky'
Diffstat (limited to 'yocto-poky/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c')
-rw-r--r-- | yocto-poky/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c | 424 |
1 files changed, 424 insertions, 0 deletions
diff --git a/yocto-poky/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c b/yocto-poky/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c new file mode 100644 index 0000000000..7f4caf9886 --- /dev/null +++ b/yocto-poky/meta/recipes-devtools/rpm/rpmresolve/rpmresolve.c @@ -0,0 +1,424 @@ +/* OpenEmbedded RPM resolver utility + + Written by: Paul Eggleton <paul.eggleton@linux.intel.com> + + Copyright 2012 Intel Corporation + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +*/ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <sys/stat.h> + +#include <rpmdb.h> +#include <rpmtypes.h> +#include <rpmtag.h> +#include <rpmts.h> +#include <rpmmacro.h> +#include <rpmcb.h> +#include <rpmlog.h> +#include <argv.h> +#include <mire.h> + +int debugmode; +FILE *outf; + +int getPackageStr(rpmts ts, const char *NVRA, rpmTag tag, char **value) +{ + int rc = -1; + rpmmi mi = rpmtsInitIterator(ts, RPMTAG_NVRA, NVRA, 0); + Header h; + if ((h = rpmmiNext(mi)) != NULL) { + HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); + he->tag = tag; + rc = (headerGet(h, he, 0) != 1); + if(rc==0) + *value = strdup((char *)he->p.ptr); + } + (void)rpmmiFree(mi); + return rc; +} + +int loadTs(rpmts **ts, int *tsct, const char *dblistfn) +{ + int count = 0; + int sz = 5; + int rc = 0; + int listfile = 1; + struct stat st_buf; + + rc = stat(dblistfn, &st_buf); + if(rc != 0) { + perror("stat"); + return 1; + } + if(S_ISDIR(st_buf.st_mode)) + listfile = 0; + + if(listfile) { + if(debugmode) + printf("DEBUG: reading database list file '%s'\n", dblistfn); + *ts = malloc(sz * sizeof(rpmts)); + FILE *f = fopen(dblistfn, "r" ); + if(f) { + char line[2048]; + while(fgets(line, sizeof(line), f)) { + int len = strlen(line) - 1; + if(len > 0) + // Trim trailing whitespace + while(len > 0 && isspace(line[len])) + line[len--] = '\0'; + + if(len > 0) { + // Expand array if needed + if(count == sz) { + sz += 5; + *ts = (rpmts *)realloc(*ts, sz); + } + + if(debugmode) + printf("DEBUG: opening database '%s'\n", line); + char *dbpathm = malloc(strlen(line) + 10); + sprintf(dbpathm, "_dbpath %s", line); + rpmDefineMacro(NULL, dbpathm, RMIL_CMDLINE); + free(dbpathm); + + rpmts tsi = rpmtsCreate(); + (*ts)[count] = tsi; + rc = rpmtsOpenDB(tsi, O_RDONLY); + if( rc ) { + fprintf(stderr, "Failed to open database %s\n", line); + rc = -1; + break; + } + + count++; + } + } + fclose(f); + *tsct = count; + } + else { + perror(dblistfn); + rc = -1; + } + } + else { + if(debugmode) + printf("DEBUG: opening database '%s'\n", dblistfn); + // Load from single database + *ts = malloc(sizeof(rpmts)); + char *dbpathm = malloc(strlen(dblistfn) + 10); + sprintf(dbpathm, "_dbpath %s", dblistfn); + rpmDefineMacro(NULL, dbpathm, RMIL_CMDLINE); + free(dbpathm); + + rpmts tsi = rpmtsCreate(); + (*ts)[0] = tsi; + rc = rpmtsOpenDB(tsi, O_RDONLY); + if( rc ) { + fprintf(stderr, "Failed to open database %s\n", dblistfn); + rc = -1; + } + *tsct = 1; + } + + return rc; +} + +int processPackages(rpmts *ts, int tscount, const char *packagelistfn, int ignoremissing) +{ + int rc = 0; + int count = 0; + int sz = 100; + int i = 0; + int missing = 0; + + FILE *f = fopen(packagelistfn, "r" ); + if(f) { + char line[255]; + while(fgets(line, sizeof(line), f)) { + int len = strlen(line) - 1; + if(len > 0) + // Trim trailing whitespace + while(len > 0 && isspace(line[len])) + line[len--] = '\0'; + + if(len > 0) { + int found = 0; + for(i=0; i<tscount; i++) { + ARGV_t keys = NULL; + rpmdb db = rpmtsGetRdb(ts[i]); + rc = rpmdbMireApply(db, RPMTAG_NAME, + RPMMIRE_STRCMP, line, &keys); + if (keys) { + int nkeys = argvCount(keys); + if( nkeys == 1 ) { + char *value = NULL; + rc = getPackageStr(ts[i], keys[0], RPMTAG_PACKAGEORIGIN, &value); + if(rc == 0) + fprintf(outf, "%s\n", value); + else + fprintf(stderr, "Failed to get package origin for %s\n", line); + found = 1; + } + else if( nkeys > 1 ) { + int keyindex = 0; + fprintf(stderr, "Multiple matches for %s:\n", line); + for( keyindex=0; keyindex<nkeys; keyindex++) { + char *value = NULL; + rc = getPackageStr(ts[i], keys[keyindex], RPMTAG_PACKAGEORIGIN, &value); + if(rc == 0) + fprintf(stderr, " %s\n", value); + else + fprintf(stderr, " (%s)\n", keys[keyindex]); + } + } + } + if(found) + break; + } + + if( !found ) { + if( ignoremissing ) { + fprintf(stderr, "Unable to resolve package %s - ignoring\n", line); + } + else { + fprintf(stderr, "Unable to resolve package %s\n", line); + missing = 1; + } + } + } + count++; + } + fclose(f); + + if( missing ) { + fprintf(stderr, "ERROR: some packages were missing\n"); + rc = 1; + } + } + else { + perror(packagelistfn); + rc = -1; + } + + return rc; +} + +int lookupProvider(rpmts ts, const char *req, char **provider) +{ + int rc = 0; + rpmmi provmi = rpmtsInitIterator(ts, RPMTAG_PROVIDENAME, req, 0); + if(provmi) { + Header h; + if ((h = rpmmiNext(provmi)) != NULL) { + HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); + he->tag = RPMTAG_NAME; + rc = (headerGet(h, he, 0) != 1); + if(rc==0) + *provider = strdup((char *)he->p.ptr); + } + (void)rpmmiFree(provmi); + } + else { + rc = -1; + } + return rc; +} + +int printDepList(rpmts *ts, int tscount) +{ + int rc = 0; + + if( tscount > 1 ) + fprintf(stderr, ">1 database specified with dependency list, using first only\n"); + + /* Get list of names */ + rpmdb db = rpmtsGetRdb(ts[0]); + ARGV_t names = NULL; + rc = rpmdbMireApply(db, RPMTAG_NAME, + RPMMIRE_STRCMP, NULL, &names); + int nnames = argvCount(names); + + /* Get list of NVRAs */ + ARGV_t keys = NULL; + rc = rpmdbMireApply(db, RPMTAG_NVRA, + RPMMIRE_STRCMP, NULL, &keys); + if (keys) { + int i, j; + HE_t he = (HE_t) memset(alloca(sizeof(*he)), 0, sizeof(*he)); + int nkeys = argvCount(keys); + for(i=0; i<nkeys; i++) { + rpmmi mi = rpmtsInitIterator(ts[0], RPMTAG_NVRA, keys[i], 0); + Header h; + if ((h = rpmmiNext(mi)) != NULL) { + /* Get name of package */ + he->tag = RPMTAG_NAME; + rc = (headerGet(h, he, 0) != 1); + char *name = strdup((char *)he->p.ptr); + /* Get its requires */ + he->tag = RPMTAG_REQUIRENAME; + if (rc = (headerGet(h, he, 0) != 1)) { + if (debugmode) { + printf("DEBUG: %s requires null\n", name); + } + rc = 0; + continue; + } + ARGV_t reqs = (ARGV_t)he->p.ptr; + /* Get its requireflags */ + he->tag = RPMTAG_REQUIREFLAGS; + rc = (headerGet(h, he, 0) != 1); + rpmuint32_t *reqflags = (rpmuint32_t *)he->p.ui32p; + for(j=0; j<he->c; j++) { + int k; + char *prov = NULL; + for(k=0; k<nnames; k++) { + if(strcmp(names[k], reqs[j]) == 0) { + prov = names[k]; + break; + } + } + if(prov) { + if((int)reqflags[j] & 0x80000) + fprintf(outf, "%s|%s [REC]\n", name, prov); + else + fprintf(outf, "%s|%s\n", name, prov); + } + else { + rc = lookupProvider(ts[0], reqs[j], &prov); + if(rc==0 && prov) { + if((int)reqflags[j] & 0x80000) + fprintf(outf, "%s|%s [REC]\n", name, prov); + else + fprintf(outf, "%s|%s\n", name, prov); + free(prov); + } + } + } + free(name); + } + (void)rpmmiFree(mi); + } + } + + return rc; +} + +void usage() +{ + fprintf(stderr, "OpenEmbedded rpm resolver utility\n"); + fprintf(stderr, "syntax: rpmresolve [-i] [-d] [-t] <dblistfile> <packagelistfile>\n"); +} + +int main(int argc, char **argv) +{ + rpmts *ts = NULL; + int tscount = 0; + int rc = 0; + int i; + int c; + int ignoremissing = 0; + int deplistmode = 0; + char *outfile = NULL; + + debugmode = 0; + outf = stdout; + + opterr = 0; + while ((c = getopt (argc, argv, "itdo:")) != -1) { + switch (c) { + case 'i': + ignoremissing = 1; + break; + case 't': + deplistmode = 1; + break; + case 'd': + debugmode = 1; + break; + case 'o': + outfile = strdup(optarg); + break; + case '?': + if(isprint(optopt)) + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + else + fprintf(stderr, "Unknown option character `\\x%x'.\n", + optopt); + usage(); + return 1; + default: + abort(); + } + } + + if( argc - optind < 1 ) { + usage(); + return 1; + } + + if( outfile ) { + if(debugmode) + printf("DEBUG: Using output file %s\n", outfile); + outf = fopen(outfile, "w"); + } + + const char *dblistfn = argv[optind]; + + rpmcliInit(argc, argv, NULL); + + if(debugmode) + rpmSetVerbosity(RPMLOG_DEBUG); + + rpmDefineMacro(NULL, "__dbi_txn create nofsync", RMIL_CMDLINE); + + rc = loadTs(&ts, &tscount, dblistfn); + if( rc ) + return 1; + if( tscount == 0 ) { + fprintf(stderr, "Please specify database list file or database location\n"); + return 1; + } + + if(deplistmode) { + rc = printDepList(ts, tscount); + } + else { + if( argc - optind < 2 ) { + fprintf(stderr, "Please specify package list file\n"); + } + else { + const char *pkglistfn = argv[optind+1]; + rc = processPackages(ts, tscount, pkglistfn, ignoremissing); + } + } + + for(i=0; i<tscount; i++) + (void) rpmtsCloseDB(ts[i]); + free(ts); + + if( outfile ) { + fclose(outf); + free(outfile); + } + + return rc; +} |