implement pool_set_rootdir/REPO_USE_ROOTDIR instead of passing a rootdir to various...
authorMichael Schroeder <mls@suse.de>
Tue, 23 Oct 2012 10:37:25 +0000 (12:37 +0200)
committerMichael Schroeder <mls@suse.de>
Tue, 23 Oct 2012 10:37:25 +0000 (12:37 +0200)
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.

17 files changed:
bindings/solv.i
examples/solv.c
ext/repo_arch.c
ext/repo_deb.c
ext/repo_deb.h
ext/repo_products.c
ext/repo_products.h
ext/repo_releasefile_products.c
ext/repo_rpmdb.c
ext/repo_rpmdb.h
ext/repo_zyppdb.c
src/libsolv.ver
src/pool.c
src/pool.h
src/repo.h
tools/findfileconflicts.c
tools/rpmdb2solv.c

index 1ef447c..ec7280f 100644 (file)
@@ -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);
index f2738a3..3c4e336 100644 (file)
@@ -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;
index 5151803..6caa487 100644 (file)
@@ -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;
 }
 
index 635a987..2e1977b 100644 (file)
@@ -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;
index 3ca3fdf..7057da6 100644 (file)
@@ -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)
index c15051a..598b2ab 100644 (file)
@@ -14,6 +14,7 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <unistd.h>
+#include <errno.h>
 #include <limits.h>
 #include <fcntl.h>
 #include <ctype.h>
@@ -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)
index 748b813..f7e3b0a 100644 (file)
@@ -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);
index e7cbc49..5c8ec33 100644 (file)
@@ -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));
index 59cd153..e0765a6 100644 (file)
@@ -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;
index 5bd436d..1e12de7 100644 (file)
@@ -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)
index 4bbc7e9..19eabd9 100644 (file)
@@ -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;
index a0e7980..16fd774 100644 (file)
@@ -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;
index f8656b4..4d33e8b 100644 (file)
@@ -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 */
index a1359a8..bf52522 100644 (file)
@@ -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
  */
index 2d2d7fc..8e5078d 100644 (file)
@@ -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);
index ea64592..1ef5592 100644 (file)
@@ -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);
index e187b13..0d00331 100644 (file)
@@ -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 <root> given, not '/', and proddir does not start with <root> */
       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);