/* OpenEmbedded RPM resolver utility Written by: Paul Eggleton 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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) { *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); } 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 { // 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 1 ) { fprintf(stderr, "Multiple matches for %s!\n", line); } } if(found) break; } if( !found ) { if( ignoremissing ) { fprintf(stderr, "unable to find package %s - ignoring\n", line); } else { fprintf(stderr, "unable to find 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 ) printf(">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; itag = RPMTAG_NAME; rc = (headerGet(h, he, 0) != 1); char *name = strdup((char *)he->p.ptr); /* Get its requires */ he->tag = RPMTAG_REQUIRENAME; rc = (headerGet(h, he, 0) != 1); 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; jc; j++) { int k; char *prov = NULL; for(k=0; k \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; opterr = 0; while ((c = getopt (argc, argv, "id")) != -1) { switch (c) { case 'i': ignoremissing = 1; break; case 'd': deplistmode = 1; 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; } const char *dblistfn = argv[optind]; //rpmSetVerbosity(RPMLOG_DEBUG); rpmReadConfigFiles( NULL, NULL ); 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"); return 1; } const char *pkglistfn = argv[optind+1]; rc = processPackages(ts, tscount, pkglistfn, ignoremissing); } for(i=0; i