- add rpm_installedrpmdbids
authorMichael Schroeder <mls@suse.de>
Mon, 22 Jun 2009 09:25:45 +0000 (11:25 +0200)
committerMichael Schroeder <mls@suse.de>
Mon, 22 Jun 2009 09:25:45 +0000 (11:25 +0200)
- fix memleaks

tools/pool_fileconflicts.c
tools/repo_rpmdb.c
tools/repo_rpmdb.h

index e14d5c4b3eb2ba43f577c760c59b9479669cfc66..1858df4cc5f0cace3e4df07a2bfdc14139eab99f 100644 (file)
@@ -21,6 +21,9 @@ struct cbdata {
   Hashval *dirmap;
   Hashmask dirmapn;
   unsigned int dirmapused;
+  int dirconflicts;
+
+  Map idxmap;
 
   Hashval idx;
   unsigned int hx;
@@ -64,7 +67,7 @@ doublehash(Hashval *map, Hashmask *mapnp)
 }
 
 static void
-finddirs_cb(void *cbdatav, char *fn, int fmode, char *md5)
+finddirs_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
 {
   struct cbdata *cbdata = cbdatav;
   Hashmask h, hh, hx, qx;
@@ -99,7 +102,12 @@ finddirs_cb(void *cbdatav, char *fn, int fmode, char *md5)
   if (cbdata->dirmap[2 * h + 1] == idx)
     return;
   /* found a conflict, this dir is used in multiple packages */
-  cbdata->dirmap[2 * h + 1] = -1;
+  if (cbdata->dirmap[2 * h + 1] != -1)
+    {
+      cbdata->dirmap[2 * h + 1] = -1;
+      cbdata->dirconflicts++;
+    }
+  MAPSET(&cbdata->idxmap, idx);
 }
 
 static inline int
@@ -121,7 +129,7 @@ isindirmap(struct cbdata *cbdata, Hashmask hx)
 }
 
 static void
-findfileconflicts_cb(void *cbdatav, char *fn, int fmode, char *md5)
+findfileconflicts_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
 {
   struct cbdata *cbdata = cbdatav;
   int isdir = S_ISDIR(fmode);
@@ -201,7 +209,7 @@ addfilesspace(struct cbdata *cbdata, unsigned char *data, int len)
 }
 
 static void
-findfileconflicts2_cb(void *cbdatav, char *fn, int fmode, char *md5)
+findfileconflicts2_cb(void *cbdatav, const char *fn, int fmode, const char *md5)
 {
   struct cbdata *cbdata = cbdatav;
   unsigned int hx = strhash(fn);
@@ -250,11 +258,12 @@ static int conflicts_cmp(const void *ap, const void *bp, void *dp)
 int
 pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata)
 {
-  int i, j, cflmapn;
+  int i, j, cflmapn, idxmapset;
   unsigned int hx;
   struct cbdata cbdata;
   unsigned int now, start;
   void *handle;
+  Id p;
 
   queue_empty(conflicts);
   if (!pkgs->count)
@@ -269,6 +278,8 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
   queue_init(&cbdata.lookat);
   queue_init(&cbdata.lookat_dir);
   queue_init(&cbdata.files);
+  map_init(&cbdata.idxmap, pkgs->count);
+
   if (cutoff <= 0)
     cutoff = pkgs->count;
 
@@ -282,20 +293,24 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
   cbdata.dirmap = sat_calloc(cflmapn, 2 * sizeof(Id));
   cbdata.dirmapn = cflmapn - 1;        /* make it a mask */
   cbdata.create = 1;
+  idxmapset = 0;
   for (i = 0; i < pkgs->count; i++)
     {
-      Id p = pkgs->elements[i];
+      p = pkgs->elements[i];
       cbdata.idx = i;
       if (i == cutoff)
        cbdata.create = 0;
       handle = (*handle_cb)(pool, p, handle_cbdata);
       if (handle)
         rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata);
+      if (MAPTST(&cbdata.idxmap, i))
+        idxmapset++;
     }
 
   POOL_DEBUG(SAT_DEBUG_STATS, "dirmap size: %d used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused);
   POOL_DEBUG(SAT_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024);
   POOL_DEBUG(SAT_DEBUG_STATS, "dirmap creation took %d ms\n", sat_timems(now));
+  POOL_DEBUG(SAT_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count);
 
   /* second pass: scan files */
   now = sat_timems(0);
@@ -307,7 +322,9 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
   cbdata.create = 1;
   for (i = 0; i < pkgs->count; i++)
     {
-      Id p = pkgs->elements[i];
+      if (!MAPTST(&cbdata.idxmap, i))
+       continue;
+      p = pkgs->elements[i];
       cbdata.idx = i;
       if (i == cutoff)
        cbdata.create = 0;
@@ -326,6 +343,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
   cbdata.cflmap = sat_free(cbdata.cflmap);
   cbdata.cflmapn = 0;
   cbdata.cflmapused = 0;
+  map_free(&cbdata.idxmap);
 
   now = sat_timems(0);
   POOL_DEBUG(SAT_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count);
@@ -348,8 +366,7 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
     {
       int pend, ii, jj;
       int pidx = cbdata.lookat.elements[i + 1];
-      Id p = pkgs->elements[pidx];
-
+      p = pkgs->elements[pidx];
       hx = cbdata.lookat.elements[i];
       if (cbdata.lookat.elements[i + 2] != hx)
        continue;       /* no package left */
@@ -393,6 +410,8 @@ pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, vo
     }
   cbdata.filesspace = sat_free(cbdata.filesspace);
   cbdata.filesspacen = 0;
+  queue_free(&cbdata.lookat);
+  queue_free(&cbdata.files);
   POOL_DEBUG(SAT_DEBUG_STATS, "candidate check took %d ms\n", sat_timems(now));
   if (conflicts->count > 5)
     sat_sort(conflicts->elements, conflicts->count / 5, 5 * sizeof(Id), conflicts_cmp, pool);
index ddb6b68e6379b808cdfbbe0bf61d9869adf14005..826fa13f26bc5f7cdb9dd071348a1e038b8222c4 100644 (file)
@@ -32,6 +32,7 @@
 #include "repo.h"
 #include "hash.h"
 #include "util.h"
+#include "queue.h"
 #include "repo_rpmdb.h"
 
 #define RPMDB_COOKIE_VERSION 2
@@ -977,6 +978,8 @@ copydeps(Pool *pool, Repo *repo, Offset fromoff, Repo *fromrepo)
   return ido;
 }
 
+#define COPYDIR_DIRCACHE_SIZE 512
+
 static Id copydir_complex(Pool *pool, Repodata *data, Stringpool *fromspool, Repodata *fromdata, Id did, Id *cache);
 
 static inline Id
@@ -1201,7 +1204,7 @@ count_headers(const char *rootdir, DB_ENV *dbenv)
     }
   if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664))
     {
-      perror("db->open var/lib/rpm/Name");
+      perror("db->open Name index");
       exit(1);
     }
   if (db->get_byteswapped(db, &byteswapped))
@@ -1287,11 +1290,6 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags)
       perror("dbenv open");
       exit(1);
     }
-  if (db_create(&db, dbenv, 0))
-    {
-      perror("db_create");
-      exit(1);
-    }
 
   /* XXX: should get ro lock of Packages database! */
   snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm/Packages", rootdir);
@@ -1311,9 +1309,14 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags)
 
       if ((flags & RPMDB_REPORT_PROGRESS) != 0)
        count = count_headers(rootdir, dbenv);
+      if (db_create(&db, dbenv, 0))
+       {
+         perror("db_create");
+         exit(1);
+       }
       if (db->open(db, 0, "Packages", 0, DB_UNKNOWN, DB_RDONLY, 0664))
        {
-         perror("db->open var/lib/rpm/Packages");
+         perror("db->open Packages index");
          exit(1);
        }
       if (db->get_byteswapped(db, &byteswapped))
@@ -1425,12 +1428,17 @@ repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags)
     }
   else
     {
-      Id dircache[512];
+      Id dircache[COPYDIR_DIRCACHE_SIZE];              /* see copydir */
 
       memset(dircache, 0, sizeof(dircache));
+      if (db_create(&db, dbenv, 0))
+       {
+         perror("db_create");
+         exit(1);
+       }
       if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664))
        {
-         perror("db->open var/lib/rpm/Name");
+         perror("db->open Name index");
          exit(1);
        }
       if (db->get_byteswapped(db, &byteswapped))
@@ -1804,14 +1812,16 @@ linkhash(const char *lt, char *hash)
 }
 
 void
-rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, char *), void *cbdata)
+rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata)
 {
   RpmHead *rpmhead = rpmhandle;
   char **bn;
   char **dn;
   char **md = 0;
   char **lt = 0;
-  unsigned int *di;
+  unsigned int *di, diidx;
+  unsigned int lastdir;
+  int lastdirl;
   unsigned int *fm;
   int cnt, dcnt, cnt2;
   int i, l1, l;
@@ -1865,11 +1875,14 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int,
          return;
        }
     }
+  lastdir = dcnt;
+  lastdirl = 0;
   for (i = 0; i < cnt; i++)
     {
-      if (di[i] >= dcnt)
+      diidx = di[i];
+      if (diidx >= dcnt)
        continue;
-      l1 = strlen(dn[di[i]]);
+      l1 = lastdir == diidx ? lastdirl : strlen(dn[diidx]);
       if (l1 == 0)
        continue;
       l = l1 + strlen(bn[i]) + 1;
@@ -1878,7 +1891,12 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int,
          spacen = l + 16;
          space = sat_realloc(space, spacen);
        }
-      strcpy(space, dn[di[i]]);
+      if (lastdir != diidx)
+       {
+          strcpy(space, dn[diidx]);
+         lastdir = diidx;
+         lastdirl = l1;
+       }
       strcpy(space + l1, bn[i]);
       if (md)
        {
@@ -1903,6 +1921,7 @@ rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int,
        }
       (*cb)(cbdata, space, fm[i], md5p);
     }
+  sat_free(space);
   sat_free(lt);
   sat_free(md);
   sat_free(fm);
@@ -1922,6 +1941,99 @@ struct rpm_by_state {
   int byteswapped;
 };
 
+int
+rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq)
+{
+  char dbpath[PATH_MAX];
+  DB_ENV *dbenv = 0;
+  DB *db = 0;
+  DBC *dbc = 0;
+  int byteswapped;
+  DBT dbkey;
+  DBT dbdata;
+  Id rpmdbid;
+  unsigned char *dp;
+  int dl, cnt;
+
+  if (rpmdbidq)
+    queue_empty(rpmdbidq);
+  cnt = 0;
+
+  if (db_env_create(&dbenv, 0))
+    {
+      perror("db_env_create");
+      return 0;
+    }
+  snprintf(dbpath, PATH_MAX, "%s/var/lib/rpm", rootdir ? rootdir : "");
+#ifdef FEDORA
+  if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL, 0))
+#else
+  if (dbenv->open(dbenv, dbpath, DB_CREATE|DB_PRIVATE|DB_INIT_MPOOL, 0))
+#endif
+    {
+      perror("dbenv open");
+      dbenv->close(dbenv, 0);
+      return 0;
+    }
+  if (db_create(&db, dbenv, 0))
+    {
+      perror("db_create");
+      dbenv->close(dbenv, 0);
+      return 0;
+    }
+  if (db->open(db, 0, "Name", 0, DB_UNKNOWN, DB_RDONLY, 0664))
+    {
+      perror("db->open Name index");
+      db->close(db, 0);
+      dbenv->close(dbenv, 0);
+      return 0;
+    }
+  if (db->get_byteswapped(db, &byteswapped))
+    {
+      perror("db->get_byteswapped");
+      db->close(db, 0);
+      dbenv->close(dbenv, 0);
+      return 0;
+    }
+  if (db->cursor(db, NULL, &dbc, 0))
+    {
+      perror("db->cursor");
+      db->close(db, 0);
+      dbenv->close(dbenv, 0);
+      return 0;
+    }
+  memset(&dbkey, 0, sizeof(dbkey));
+  memset(&dbdata, 0, sizeof(dbdata));
+  while (dbc->c_get(dbc, &dbkey, &dbdata, DB_NEXT) == 0)
+    {
+      if (dbkey.size == 10 && !memcmp(dbkey.data, "gpg-pubkey", 10))
+       continue;
+      dl = dbdata.size;
+      dp = dbdata.data;
+      while(dl >= 8)
+       {
+         if (byteswapped)
+           {
+             ((char *)&rpmdbid)[0] = dp[3];
+             ((char *)&rpmdbid)[1] = dp[2];
+             ((char *)&rpmdbid)[2] = dp[1];
+             ((char *)&rpmdbid)[3] = dp[0];
+           }
+         else
+           memcpy((char *)&rpmdbid, dp, 4);
+         if (rpmdbidq)
+           queue_push(rpmdbidq, rpmdbid);
+         cnt++;
+         dp += 8;
+         dl -= 8;
+       }
+    }
+  dbc->c_close(dbc);
+  db->close(db, 0);
+  dbenv->close(dbenv, 0);
+  return cnt;
+}
+
 void *
 rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep)
 {
index 6c907c7d3c9aebf5b58b13186ccece3691aeb32a..3e80302f3f0e8e12aaa390a920ea4b7149d30dab 100644 (file)
@@ -5,6 +5,8 @@
  * for further information
  */
 
+#include "queue.h"
+
 extern void repo_add_rpmdb(Repo *repo, Repo *ref, const char *rootdir, int flags);
 extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags);
 
@@ -15,4 +17,5 @@ extern void repo_add_rpms(Repo *repo, const char **rpms, int nrpms, int flags);
 
 void *rpm_byrpmdbid(Id rpmdbid, const char *rootdir, void **statep);
 void *rpm_byfp(FILE *fp, const char *name, void **statep);
-void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, char *, int, char *), void *cbdata);
+void rpm_iterate_filelist(void *rpmhandle, int flags, void (*cb)(void *, const char *, int, const char *), void *cbdata);
+int  rpm_installedrpmdbids(const char *rootdir, Queue *rpmdbidq);