From 765ead528d2b791e43e2a90212b5e4a0c2ad1302 Mon Sep 17 00:00:00 2001 From: Michael Schroeder Date: Tue, 23 Oct 2012 12:37:25 +0200 Subject: [PATCH] implement pool_set_rootdir/REPO_USE_ROOTDIR instead of passing a rootdir to various functions. Breaks the interface a bit, sorry. The new way seems to be much cleaner, though. Extra apologies to Nate Skulic for removing his add_rpmdb_root method one day after adding it. --- bindings/solv.i | 49 +++++++++------------- examples/solv.c | 92 ++++++++++++++++++++++++----------------- ext/repo_arch.c | 6 ++- ext/repo_deb.c | 8 ++-- ext/repo_deb.h | 2 +- ext/repo_products.c | 41 +++++++++++------- ext/repo_products.h | 2 +- ext/repo_releasefile_products.c | 12 +++++- ext/repo_rpmdb.c | 21 ++++++---- ext/repo_rpmdb.h | 4 +- ext/repo_zyppdb.c | 4 ++ src/libsolv.ver | 4 ++ src/pool.c | 34 +++++++++++++++ src/pool.h | 8 ++++ src/repo.h | 1 + tools/findfileconflicts.c | 2 +- tools/rpmdb2solv.c | 23 +++++------ 17 files changed, 196 insertions(+), 117 deletions(-) diff --git a/bindings/solv.i b/bindings/solv.i index 1ef447c..ec7280f 100644 --- a/bindings/solv.i +++ b/bindings/solv.i @@ -827,6 +827,12 @@ typedef struct { int get_flag(int flag) { return pool_get_flag($self, flag); } + void set_rootdir(const char *rootdir) { + pool_set_rootdir($self, rootdir); + } + const char *get_rootdir(int flag) { + return pool_get_rootdir($self); + } #if defined(SWIGPYTHON) %{ SWIGINTERN int loadcallback(Pool *pool, Repodata *data, void *d) { @@ -1088,6 +1094,7 @@ typedef struct { static const int REPO_LOCALPOOL = REPO_LOCALPOOL; static const int REPO_USE_LOADING = REPO_USE_LOADING; static const int REPO_EXTEND_SOLVABLES = REPO_EXTEND_SOLVABLES; + static const int REPO_USE_ROOTDIR = REPO_USE_ROOTDIR; static const int SOLV_ADD_NO_STUBS = SOLV_ADD_NO_STUBS; /* repo_solv */ #ifdef ENABLE_SUSEREPO static const int SUSETAGS_RECORD_SHARES = SUSETAGS_RECORD_SHARES; /* repo_susetags */ @@ -1125,41 +1132,29 @@ typedef struct { #ifdef ENABLE_RPMDB bool add_rpmdb(Repo *ref, int flags = 0) { - repo_add_rpmdb($self, ref, 0, flags); - return 1; - } - - bool add_rpmdb_root(Repo *ref, const char *root, int flags = 0) { - repo_add_rpmdb($self, ref, root, flags); - return 1; + return repo_add_rpmdb($self, ref, flags); } - Id add_rpm(const char *name, int flags = 0) { return repo_add_rpm($self, name, flags); } #endif #ifdef ENABLE_RPMMD bool add_rpmmd(FILE *fp, const char *language, int flags = 0) { - repo_add_rpmmd($self, fp, language, flags); - return 1; + return repo_add_rpmmd($self, fp, language, flags); } bool add_repomdxml(FILE *fp, int flags = 0) { - repo_add_repomdxml($self, fp, flags); - return 1; + return repo_add_repomdxml($self, fp, flags); } bool add_updateinfoxml(FILE *fp, int flags = 0) { - repo_add_updateinfoxml($self, fp, flags); - return 1; + return repo_add_updateinfoxml($self, fp, flags); } bool add_deltainfoxml(FILE *fp, int flags = 0) { - repo_add_deltainfoxml($self, fp, flags); - return 1; + return repo_add_deltainfoxml($self, fp, flags); } #endif #ifdef ENABLE_DEBIAN bool add_debdb(int flags = 0) { - repo_add_debdb($self, 0, flags); - return 1; + return repo_add_debdb($self, flags); } Id add_deb(const char *name, int flags = 0) { return repo_add_deb($self, name, flags); @@ -1167,32 +1162,26 @@ typedef struct { #endif #ifdef ENABLE_SUSEREPO bool add_susetags(FILE *fp, Id defvendor, const char *language, int flags = 0) { - repo_add_susetags($self, fp, defvendor, language, flags); - return 1; + return repo_add_susetags($self, fp, defvendor, language, flags); } bool add_content(FILE *fp, int flags = 0) { - repo_add_content($self, fp, flags); - return 1; + return repo_add_content($self, fp, flags); } bool add_products(const char *proddir, int flags = 0) { - repo_add_products($self, proddir, 0, flags); - return 1; + return repo_add_products($self, proddir, flags); } #endif #ifdef ENABLE_MDKREPO bool add_mdk(FILE *fp, int flags = 0) { - repo_add_mdk($self, fp, flags); - return 1; + return repo_add_mdk($self, fp, flags); } bool add_mdk_info(FILE *fp, int flags = 0) { - repo_add_mdk($self, fp, flags); - return 1; + return repo_add_mdk($self, fp, flags); } #endif #ifdef ENABLE_ARCHREPO bool add_arch_repo(FILE *fp, int flags = 0) { - repo_add_arch_repo($self, fp, flags); - return 1; + return repo_add_arch_repo($self, fp, flags); } Id add_arch_pkg(const char *name, int flags = 0) { return repo_add_arch_pkg($self, name, flags); diff --git a/examples/solv.c b/examples/solv.c index f2738a3..3c4e336 100644 --- a/examples/solv.c +++ b/examples/solv.c @@ -140,14 +140,15 @@ yum_substitute(Pool *pool, char *line) if (!releaseevr) { Queue q; + const char *rootdir = pool_get_rootdir(pool); queue_init(&q); - rpm_installedrpmdbids(0, "Providename", "redhat-release", &q); + rpm_installedrpmdbids(rootdir, "Providename", "redhat-release", &q); if (q.count) { void *handle, *state = 0; char *p; - handle = rpm_byrpmdbid(q.elements[0], 0, &state); + handle = rpm_byrpmdbid(q.elements[0], rootdir, &state); releaseevr = rpm_query(handle, SOLVABLE_EVR); rpm_byrpmdbid(0, 0, &state); if ((p = strchr(releaseevr, '-')) != 0) @@ -155,7 +156,10 @@ yum_substitute(Pool *pool, char *line) } queue_free(&q); if (!releaseevr) - releaseevr = strdup("?"); + { + fprintf(stderr, "no installed package provides 'redhat-release', cannot determine $releasever\n"); + exit(1); + } } *p2 = 0; p = pool_tmpjoin(pool, line, releaseevr, p2 + 11); @@ -1224,7 +1228,7 @@ read_sigs() Pool *sigpool = pool_create(); #if defined(ENABLE_RPMDB_PUBKEY) Repo *repo = repo_create(sigpool, "rpmdbkeys"); - repo_add_rpmdb_pubkeys(repo, 0, 0); + repo_add_rpmdb_pubkeys(repo, 0); #endif return sigpool; } @@ -1661,12 +1665,12 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) repo = repo_create(pool, "@System"); #if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) printf("rpm database:"); - if (stat("/var/lib/rpm/Packages", &stb)) + if (stat(pool_prepend_rootdir_tmp(pool, "/var/lib/rpm/Packages"), &stb)) memset(&stb, 0, sizeof(&stb)); #endif #if defined(ENABLE_DEBIAN) && defined(DEBIAN) printf("dpgk database:"); - if (stat("/var/lib/dpkg/status", &stb)) + if (stat(pool_prepend_rootdir_tmp(pool, "/var/lib/dpkg/status"), &stb)) memset(&stb, 0, sizeof(&stb)); #endif #ifdef NOSYSTEM @@ -1680,13 +1684,13 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) { #if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) FILE *ofp; - int done = 0; + Repo *ref = 0; #endif printf(" reading\n"); #if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) # if defined(ENABLE_SUSEREPO) && defined(PRODUCTS_PATH) - if (repo_add_products(repo, PRODUCTS_PATH, 0, REPO_NO_INTERNALIZE)) + if (repo_add_products(repo, PRODUCTS_PATH, REPO_NO_INTERNALIZE | REPO_USE_ROOTDIR)) { fprintf(stderr, "product reading failed: %s\n", pool_errstr(pool)); exit(1); @@ -1694,30 +1698,24 @@ read_repos(Pool *pool, struct repoinfo *repoinfos, int nrepoinfos) # endif if ((ofp = fopen(calccachepath(repo, 0), "r")) != 0) { - Repo *ref = repo_create(pool, "@System.old"); - if (!repo_add_solv(ref, ofp, 0)) + ref = repo_create(pool, "@System.old"); + if (repo_add_solv(ref, ofp, 0)) { - if (repo_add_rpmdb(repo, ref, 0, REPO_REUSE_REPODATA)) - { - fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); - exit(1); - } - done = 1; + repo_free(ref, 1); + ref = 0; } fclose(ofp); - repo_free(ref, 1); } - if (!done) + if (repo_add_rpmdb(repo, ref, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR)) { - if (repo_add_rpmdb(repo, 0, 0, REPO_REUSE_REPODATA)) - { - fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); - exit(1); - } + fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); + exit(1); } + if (ref) + repo_free(ref, 1); #endif #if defined(ENABLE_DEBIAN) && defined(DEBIAN) - if (repo_add_debdb(repo, 0, REPO_REUSE_REPODATA)) + if (repo_add_debdb(repo, 0, REPO_REUSE_REPODATA | REPO_USE_ROOTDIR) && !rootdir) { fprintf(stderr, "installed db: %s\n", pool_errstr(pool)); exit(1); @@ -2449,7 +2447,7 @@ fileconflict_cb(Pool *pool, Id p, void *cbdata) void -runrpm(const char *arg, const char *name, int dupfd3) +runrpm(const char *arg, const char *name, int dupfd3, const char *rootdir) { pid_t pid; int status; @@ -2461,6 +2459,8 @@ runrpm(const char *arg, const char *name, int dupfd3) } if (pid == 0) { + if (!rootdir) + rootdir = "/"; if (dupfd3 != -1 && dupfd3 != 3) { dup2(dupfd3, 3); @@ -2469,9 +2469,9 @@ runrpm(const char *arg, const char *name, int dupfd3) if (dupfd3 != -1) fcntl(3, F_SETFD, 0); /* clear CLOEXEC */ if (strcmp(arg, "-e") == 0) - execlp("rpm", "rpm", arg, "--nodeps", "--nodigest", "--nosignature", name, (char *)0); + execlp("rpm", "rpm", arg, "--nodeps", "--nodigest", "--nosignature", "--root", rootdir, name, (char *)0); else - execlp("rpm", "rpm", arg, "--force", "--nodeps", "--nodigest", "--nosignature", name, (char *)0); + execlp("rpm", "rpm", arg, "--force", "--nodeps", "--nodigest", "--nosignature", "--root", rootdir, name, (char *)0); perror("rpm"); _exit(0); } @@ -2489,7 +2489,7 @@ runrpm(const char *arg, const char *name, int dupfd3) #if defined(ENABLE_DEBIAN) && defined(DEBIAN) void -rundpkg(const char *arg, const char *name, int dupfd3) +rundpkg(const char *arg, const char *name, int dupfd3, const char *rootdir) { pid_t pid; int status; @@ -2501,6 +2501,8 @@ rundpkg(const char *arg, const char *name, int dupfd3) } if (pid == 0) { + if (!rootdir) + rootdir = "/"; if (dupfd3 != -1 && dupfd3 != 3) { dup2(dupfd3, 3); @@ -2509,9 +2511,9 @@ rundpkg(const char *arg, const char *name, int dupfd3) if (dupfd3 != -1) fcntl(3, F_SETFD, 0); /* clear CLOEXEC */ if (strcmp(arg, "--install") == 0) - execlp("dpkg", "dpkg", "--install", "--force", "all", name, (char *)0); + execlp("dpkg", "dpkg", "--install", "--root", rootdir, "--force", "all", name, (char *)0); else - execlp("dpkg", "dpkg", "--remove", "--force", "all", name, (char *)0); + execlp("dpkg", "dpkg", "--remove", "--root", rootdir, "--force", "all", name, (char *)0); perror("dpkg"); _exit(0); } @@ -2768,6 +2770,7 @@ main(int argc, char **argv) Queue addedfileprovides_inst; Id repofilter = 0; int cleandeps = 0; + char *rootdir = 0; argc--; argv++; @@ -2826,14 +2829,27 @@ main(int argc, char **argv) else usage(1); - if (argc > 1 && !strcmp(argv[1], "--clean")) + for (;;) { - cleandeps = 1; - argc--; - argv++; + if (argc > 2 && !strcmp(argv[1], "--root")) + { + rootdir = argv[2]; + argc -= 2; + argv += 2; + } + + else if (argc > 1 && !strcmp(argv[1], "--clean")) + { + cleandeps = 1; + argc--; + argv++; + } + else + break; } pool = pool_create(); + pool_set_rootdir(pool, rootdir); #if 0 { @@ -3477,10 +3493,10 @@ rerunsolver: evr = evrp + 1; nvra = pool_tmpjoin(pool, pool_id2str(pool, s->name), "-", evr); nvra = pool_tmpappend(pool, nvra, ".", pool_id2str(pool, s->arch)); - runrpm("-e", nvra, -1); /* too bad that --querybynumber doesn't work */ + runrpm("-e", nvra, -1, rootdir); /* too bad that --querybynumber doesn't work */ #endif #if defined(ENABLE_DEBIAN) && defined(DEBIAN) - rundpkg("--remove", pool_id2str(pool, s->name), 0); + rundpkg("--remove", pool_id2str(pool, s->name), 0, rootdir); #endif break; case SOLVER_TRANSACTION_INSTALL: @@ -3495,10 +3511,10 @@ rerunsolver: rewind(fp); lseek(fileno(fp), 0, SEEK_SET); #if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA)) - runrpm(type == SOLVER_TRANSACTION_MULTIINSTALL ? "-i" : "-U", "/dev/fd/3", fileno(fp)); + runrpm(type == SOLVER_TRANSACTION_MULTIINSTALL ? "-i" : "-U", "/dev/fd/3", fileno(fp), rootdir); #endif #if defined(ENABLE_DEBIAN) && defined(DEBIAN) - rundpkg("--install", "/dev/fd/3", fileno(fp)); + rundpkg("--install", "/dev/fd/3", fileno(fp), rootdir); #endif fclose(fp); newpkgsfps[j] = 0; diff --git a/ext/repo_arch.c b/ext/repo_arch.c index 5151803..6caa487 100644 --- a/ext/repo_arch.c +++ b/ext/repo_arch.c @@ -342,7 +342,7 @@ repo_add_arch_pkg(Repo *repo, const char *fn, int flags) void *pkgidhandle = 0; data = repo_add_repodata(repo, flags); - if ((fd = open(fn, O_RDONLY, 0)) < 0) + if ((fd = open(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, fn) : fn, O_RDONLY, 0)) < 0) { pool_error(pool, -1, "%s: %s", fn, strerror(errno)); return 0; @@ -816,6 +816,8 @@ repo_add_arch_local(Repo *repo, const char *dir, int flags) data = repo_add_repodata(repo, flags); + if (flags & REPO_USE_ROOTDIR) + dir = pool_prepend_rootdir(pool, dir); dp = opendir(dir); if (dp) { @@ -849,6 +851,8 @@ repo_add_arch_local(Repo *repo, const char *dir, int flags) } if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); + if (flags & REPO_USE_ROOTDIR) + solv_free(dir); return 0; } diff --git a/ext/repo_deb.c b/ext/repo_deb.c index 635a987..2e1977b 100644 --- a/ext/repo_deb.c +++ b/ext/repo_deb.c @@ -414,12 +414,12 @@ repo_add_debpackages(Repo *repo, FILE *fp, int flags) } int -repo_add_debdb(Repo *repo, const char *rootdir, int flags) +repo_add_debdb(Repo *repo, int flags) { FILE *fp; const char *path = "/var/lib/dpkg/status"; - if (rootdir) - path = pool_tmpjoin(repo->pool, rootdir, path, 0); + if (flags & REPO_USE_ROOTDIR) + path = pool_prepend_rootdir_tmp(repo->pool, path); if ((fp = fopen(path, "r")) == 0) return pool_error(repo->pool, -1, "%s: %s", path, strerror(errno)); repo_add_debpackages(repo, fp, flags); @@ -443,7 +443,7 @@ repo_add_deb(Repo *repo, const char *deb, int flags) struct stat stb; data = repo_add_repodata(repo, flags); - if ((fp = fopen(deb, "r")) == 0) + if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, deb) : deb, "r")) == 0) { pool_error(pool, -1, "%s: %s", deb, strerror(errno)); return 0; diff --git a/ext/repo_deb.h b/ext/repo_deb.h index 3ca3fdf..7057da6 100644 --- a/ext/repo_deb.h +++ b/ext/repo_deb.h @@ -6,7 +6,7 @@ */ extern int repo_add_debpackages(Repo *repo, FILE *fp, int flags); -extern int repo_add_debdb(Repo *repo, const char *rootdir, int flags); +extern int repo_add_debdb(Repo *repo, int flags); extern Id repo_add_deb(Repo *repo, const char *deb, int flags); #define DEBS_ADD_WITH_PKGID (1 << 8) diff --git a/ext/repo_products.c b/ext/repo_products.c index c15051a..598b2ab 100644 --- a/ext/repo_products.c +++ b/ext/repo_products.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -435,6 +436,8 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) pd.sbtab[sw->to] = sw->from; } + if (flags & REPO_USE_ROOTDIR) + dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (dir) { @@ -470,6 +473,8 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) } solv_free(pd.content); join_freemem(&pd.jd); + if (flags & REPO_USE_ROOTDIR) + solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); @@ -492,15 +497,14 @@ repo_add_code11_products(Repo *repo, const char *dirpath, int flags) /* Oh joy! Three parsers for the price of one! */ int -repo_add_products(Repo *repo, const char *proddir, const char *root, int flags) +repo_add_products(Repo *repo, const char *proddir, int flags) { - char *fullpath; + const char *fullpath; DIR *dir; - int ret; if (proddir) { - dir = opendir(proddir); + dir = opendir(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(repo->pool, proddir) : proddir); if (dir) { /* assume code11 stype products */ @@ -510,32 +514,37 @@ repo_add_products(Repo *repo, const char *proddir, const char *root, int flags) } /* code11 didn't work, try old code10 zyppdb */ - fullpath = solv_dupjoin(root ? root : 0, "/var/lib/zypp/db/products", 0); + fullpath = "/var/lib/zypp/db/products"; + if (flags & REPO_USE_ROOTDIR) + fullpath = pool_prepend_rootdir_tmp(repo->pool, fullpath); dir = opendir(fullpath); if (dir) { closedir(dir); /* assume code10 style products */ - ret = repo_add_zyppdb_products(repo, fullpath, flags); - solv_free(fullpath); - return ret; + return repo_add_zyppdb_products(repo, "/var/lib/zypp/db/products", flags); } - solv_free(fullpath); /* code10/11 didn't work, try -release files parsing */ - fullpath = solv_dupjoin(root ? root : 0, "/etc", 0); + fullpath = "/etc"; + if (flags & REPO_USE_ROOTDIR) + fullpath = pool_prepend_rootdir_tmp(repo->pool, fullpath); dir = opendir(fullpath); if (dir) { closedir(dir); - ret = repo_add_releasefile_products(repo, fullpath, flags); - solv_free(fullpath); - return ret; + return repo_add_releasefile_products(repo, "/etc", flags); } - /* no luck. print an error message in case the root argument is wrong */ - perror(fullpath); - solv_free(fullpath); + /* no luck. check if the rootdir exists */ + fullpath = pool_get_rootdir(repo->pool); + if (fullpath && *fullpath) + { + dir = opendir(fullpath); + if (!dir) + return pool_error(repo->pool, -1, "%s: %s", fullpath, strerror(errno)); + closedir(dir); + } /* the least we can do... */ if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) diff --git a/ext/repo_products.h b/ext/repo_products.h index 748b813..f7e3b0a 100644 --- a/ext/repo_products.h +++ b/ext/repo_products.h @@ -6,4 +6,4 @@ */ extern int repo_add_code11_products(Repo *repo, const char *dirpath, int flags); -extern int repo_add_products(Repo *repo, const char *proddir, const char *root, int flags); +extern int repo_add_products(Repo *repo, const char *proddir, int flags); diff --git a/ext/repo_releasefile_products.c b/ext/repo_releasefile_products.c index e7cbc49..5c8ec33 100644 --- a/ext/repo_releasefile_products.c +++ b/ext/repo_releasefile_products.c @@ -125,9 +125,17 @@ repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags) char *fullpath; struct parsedata pd; + if (!dirpath) + dirpath = "/etc"; + if (flags & REPO_USE_ROOTDIR) + dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (!dir) - return 0; + { + if (flags & REPO_USE_ROOTDIR) + solv_free((char *)dirpath); + return 0; + } memset(&pd, 0, sizeof(pd)); pd.repo = repo; @@ -151,6 +159,8 @@ repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags) } closedir(dir); join_freemem(&pd.jd); + if (flags & REPO_USE_ROOTDIR) + solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) repodata_internalize(repo_last_repodata(repo)); diff --git a/ext/repo_rpmdb.c b/ext/repo_rpmdb.c index 59cd153..e0765a6 100644 --- a/ext/repo_rpmdb.c +++ b/ext/repo_rpmdb.c @@ -1345,7 +1345,7 @@ count_headers(const char *rootdir, DB_ENV *dbenv) DBT dbkey; DBT dbdata; - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Name", rootdir); + snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Name", rootdir ? rootdir : ""); if (stat(dbpath, &statbuf)) return 0; memset(&dbkey, 0, sizeof(dbkey)); @@ -1378,7 +1378,7 @@ count_headers(const char *rootdir, DB_ENV *dbenv) */ int -repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) +repo_add_rpmdb(Repo *repo, Repo *ref, int flags) { Pool *pool = repo->pool; unsigned char buf[16]; @@ -1406,26 +1406,26 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags) Repodata *data; int count = 0, done = 0; unsigned int now; + const char *rootdir = 0; now = solv_timems(0); memset(&dbkey, 0, sizeof(dbkey)); memset(&dbdata, 0, sizeof(dbdata)); - if (!rootdir) - rootdir = ""; - data = repo_add_repodata(repo, flags); if (ref && !(ref->nsolvables && ref->rpmdbid)) ref = 0; + if (flags & REPO_USE_ROOTDIR) + rootdir = pool_get_rootdir(pool); if (!(dbenv = opendbenv(rootdir))) { return pool_error(pool, -1, "repo_add_rpmdb: opendbenv failed"); } /* XXX: should get ro lock of Packages database! */ - snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Packages", rootdir); + snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Packages", rootdir ? rootdir : ""); if (stat(dbpath, &packagesstat)) { return pool_error(pool, -1, "repo_add_rpmdb: %s: %s", dbpath, strerror(errno)); @@ -1818,7 +1818,7 @@ repo_add_rpm(Repo *repo, const char *rpm, int flags) else if ((flags & RPM_ADD_WITH_SHA1SUM) != 0) chksumtype = REPOKEY_TYPE_SHA1; - if ((fp = fopen(rpm, "r")) == 0) + if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, rpm) : rpm, "r")) == 0) { pool_error(pool, -1, "%s: %s", rpm, strerror(errno)); return 0; @@ -3182,7 +3182,7 @@ pubkey2solvable(Solvable *s, Repodata *data, char *pubkey) } int -repo_add_rpmdb_pubkeys(Repo *repo, const char *rootdir, int flags) +repo_add_rpmdb_pubkeys(Repo *repo, int flags) { Pool *pool = repo->pool; struct rpm_by_state state; @@ -3192,8 +3192,11 @@ repo_add_rpmdb_pubkeys(Repo *repo, const char *rootdir, int flags) unsigned int u32; Repodata *data; Solvable *s; + const char *rootdir = 0; data = repo_add_repodata(repo, flags); + if (flags & REPO_USE_ROOTDIR) + rootdir = pool_get_rootdir(pool); memset(&state, 0, sizeof(state)); if (!(state.dbenv = opendbenv(rootdir))) @@ -3238,7 +3241,7 @@ repo_add_pubkey(Repo *repo, const char *key, int flags) data = repo_add_repodata(repo, flags); buf = 0; bufl = 0; - if ((fp = fopen(key, "r")) == 0) + if ((fp = fopen(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(pool, key) : key, "r")) == 0) { pool_error(pool, -1, "%s: %s", key, strerror(errno)); return 0; diff --git a/ext/repo_rpmdb.h b/ext/repo_rpmdb.h index 5bd436d..1e12de7 100644 --- a/ext/repo_rpmdb.h +++ b/ext/repo_rpmdb.h @@ -10,9 +10,9 @@ struct headerToken_s; -extern int repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags); +extern int repo_add_rpmdb(Repo *repo, Repo *ref, int flags); extern Id repo_add_rpm(Repo *repo, const char *rpm, int flags); -extern int repo_add_rpmdb_pubkeys(Repo *repo, const char *rootdir, int flags); +extern int repo_add_rpmdb_pubkeys(Repo *repo, int flags); extern Id repo_add_pubkey(Repo *repo, const char *key, int flags); #define RPMDB_REPORT_PROGRESS (1 << 8) diff --git a/ext/repo_zyppdb.c b/ext/repo_zyppdb.c index 4bbc7e9..19eabd9 100644 --- a/ext/repo_zyppdb.c +++ b/ext/repo_zyppdb.c @@ -332,6 +332,8 @@ repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags) pd.sbtab[sw->to] = sw->from; } + if (flags & REPO_USE_ROOTDIR) + dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (dir) { @@ -353,6 +355,8 @@ repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags) free(pd.content); join_freemem(&pd.jd); + if (flags & REPO_USE_ROOTDIR) + solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; diff --git a/src/libsolv.ver b/src/libsolv.ver index a0e7980..16fd774 100644 --- a/src/libsolv.ver +++ b/src/libsolv.ver @@ -66,6 +66,7 @@ SOLV_1.0 { pool_freetmpspace; pool_freewhatprovides; pool_get_flag; + pool_get_rootdir; pool_id2evr; pool_id2langid; pool_id2rel; @@ -79,12 +80,15 @@ SOLV_1.0 { pool_lookup_void; pool_match_dep; pool_match_nevr_rel; + pool_prepend_rootdir; + pool_prepend_rootdir_tmp; pool_queuetowhatprovides; pool_rel2id; pool_search; pool_set_flag; pool_set_installed; pool_set_languages; + pool_set_rootdir; pool_setarch; pool_setarchpolicy; pool_setdebugcallback; diff --git a/src/pool.c b/src/pool.c index f8656b4..4d33e8b 100644 --- a/src/pool.c +++ b/src/pool.c @@ -110,6 +110,7 @@ pool_free(Pool *pool) solv_free(pool->languages); solv_free(pool->languagecache); solv_free(pool->errstr); + solv_free(pool->rootdir); solv_free(pool); } @@ -2098,4 +2099,37 @@ pool_add_fileconflicts_deps(Pool *pool, Queue *conflicts) pool_freeidhashes(pool); } +char * +pool_prepend_rootdir(Pool *pool, const char *path) +{ + if (!path) + return 0; + if (!pool->rootdir) + return solv_strdup(path); + return solv_dupjoin(pool->rootdir, "/", *path == '/' ? path + 1 : path); +} + +const char * +pool_prepend_rootdir_tmp(Pool *pool, const char *path) +{ + if (!path) + return 0; + if (!pool->rootdir) + return path; + return pool_tmpjoin(pool, pool->rootdir, "/", *path == '/' ? path + 1 : path); +} + +void +pool_set_rootdir(Pool *pool, const char *rootdir) +{ + solv_free(pool->rootdir); + pool->rootdir = solv_strdup(rootdir); +} + +const char * +pool_get_rootdir(Pool *pool) +{ + return pool->rootdir; +} + /* EOF */ diff --git a/src/pool.h b/src/pool.h index a1359a8..bf52522 100644 --- a/src/pool.h +++ b/src/pool.h @@ -143,6 +143,9 @@ struct _Pool { char *errstr; /* last error string */ int errstra; /* allocated space for errstr */ + + char *rootdir; + #endif }; @@ -231,6 +234,11 @@ extern void pool_set_installed(Pool *pool, struct _Repo *repo); extern int pool_error(Pool *pool, int ret, const char *format, ...) __attribute__((format(printf, 3, 4))); extern char *pool_errstr(Pool *pool); +extern void pool_set_rootdir(Pool *pool, const char *rootdir); +extern const char *pool_get_rootdir(Pool *pool); +extern char *pool_prepend_rootdir(Pool *pool, const char *dir); +extern const char *pool_prepend_rootdir_tmp(Pool *pool, const char *dir); + /** * Solvable management */ diff --git a/src/repo.h b/src/repo.h index 2d2d7fc..8e5078d 100644 --- a/src/repo.h +++ b/src/repo.h @@ -113,6 +113,7 @@ static inline int pool_installable(const Pool *pool, Solvable *s) #define REPO_LOCALPOOL (1 << 2) #define REPO_USE_LOADING (1 << 3) #define REPO_EXTEND_SOLVABLES (1 << 4) +#define REPO_USE_ROOTDIR (1 << 5) Repodata *repo_add_repodata(Repo *repo, int flags); Repodata *repo_id2repodata(Repo *repo, Id id); diff --git a/tools/findfileconflicts.c b/tools/findfileconflicts.c index ea64592..1ef5592 100644 --- a/tools/findfileconflicts.c +++ b/tools/findfileconflicts.c @@ -45,7 +45,7 @@ int main(int argc, char **argv) pool_setdebuglevel(pool, 1); installed = repo_create(pool, "@System"); pool_set_installed(pool, installed); - if (repo_add_rpmdb(installed, 0, 0, 0)) + if (repo_add_rpmdb(installed, 0, 0)) { fprintf(stderr, "findfileconflicts: %s\n", pool_errstr(pool)); exit(1); diff --git a/tools/rpmdb2solv.c b/tools/rpmdb2solv.c index e187b13..0d00331 100644 --- a/tools/rpmdb2solv.c +++ b/tools/rpmdb2solv.c @@ -113,7 +113,7 @@ main(int argc, char **argv) if (optind < argc) refname = argv[optind]; - if (refname) + if (refname && !nopacks) { FILE *fp; if ((fp = fopen(refname, "r")) == NULL) @@ -146,12 +146,15 @@ main(int argc, char **argv) * write .solv */ + if (root && *root) + pool_set_rootdir(pool, root); + repo = repo_create(pool, "installed"); data = repo_add_repodata(repo, 0); if (!nopacks) { - if (repo_add_rpmdb(repo, ref, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0))) + if (repo_add_rpmdb(repo, ref, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE | (percent ? RPMDB_REPORT_PROGRESS : 0))) { fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool)); exit(1); @@ -161,27 +164,21 @@ main(int argc, char **argv) #ifdef ENABLE_SUSEREPO if (proddir && *proddir) { - char *buf = proddir; - /* if given, not '/', and proddir does not start with */ if (root && *root) { int rootlen = strlen(root); - if (strncmp(root, proddir, rootlen)) + if (!strncmp(root, proddir, rootlen)) { - buf = (char *)solv_malloc(rootlen + strlen(proddir) + 2); /* + '/' + \0 */ - strcpy(buf, root); - if (root[rootlen - 1] != '/' && *proddir != '/') - buf[rootlen++] = '/'; - strcpy(buf + rootlen, proddir); + proddir += rootlen; + if (*proddir != '/' && proddir[-1] == '/') + proddir--; } } - if (repo_add_products(repo, buf, root, REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE)) + if (repo_add_products(repo, proddir, REPO_USE_ROOTDIR | REPO_REUSE_REPODATA | REPO_NO_INTERNALIZE)) { fprintf(stderr, "rpmdb2solv: %s\n", pool_errstr(pool)); exit(1); } - if (buf != proddir) - solv_free(buf); } #endif repodata_internalize(data); -- 2.7.4