Пример #1
0
FILE *
solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode)
{
  struct bufcookie *bc;
  FILE *fp;
  if (*mode != 'r' && *mode != 'w')
    return 0;
  bc = solv_calloc(1, sizeof(*bc));
  bc->freemem = 0;
  bc->bufp = bufp;
  if (!buflp)
    {
      bc->bufl_int = *mode == 'w' ? 0 : strlen(*bufp);
      buflp = &bc->bufl_int;
    }
  bc->buflp = buflp;
  if (*mode == 'w')
    {
      *bc->bufp = solv_extend(0, 0, 1, 1, 4095);	/* always zero-terminate */
      (*bc->bufp)[0] = 0;
      *bc->buflp = 0;
    }
  fp = cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose);
  if (!strcmp(mode, "rf"))	/* auto-free */
    bc->freemem = *bufp;
  if (!fp)
    {
      if (*mode == 'w')
	*bc->bufp = solv_free(*bc->bufp);
      cookie_bufclose(bc);
    }
  return fp;
}
Пример #2
0
Chksum *
solv_chksum_create(Id type)
{
  Chksum *chk;
  chk = solv_calloc(1, sizeof(*chk));
  chk->type = type;
  switch(type)
    {
    case REPOKEY_TYPE_MD5:
      solv_MD5_Init(&chk->c.md5);
      return chk;
    case REPOKEY_TYPE_SHA1:
      solv_SHA1_Init(&chk->c.sha1);
      return chk;
    case REPOKEY_TYPE_SHA224:
      solv_SHA224_Init(&chk->c.sha224);
      return chk;
    case REPOKEY_TYPE_SHA256:
      solv_SHA256_Init(&chk->c.sha256);
      return chk;
    case REPOKEY_TYPE_SHA384:
      solv_SHA384_Init(&chk->c.sha384);
      return chk;
    case REPOKEY_TYPE_SHA512:
      solv_SHA512_Init(&chk->c.sha512);
      return chk;
    default:
      break;
    }
  free(chk);
  return 0;
}
Пример #3
0
static struct Solutions *
solutions_create(void)
{
    struct Solutions *solutions = solv_calloc(1, sizeof(struct Solutions));
    solutions->installs = hy_packagelist_create();
    return solutions;
}
Пример #4
0
static Hashtable
growhash(Hashtable map, Hashval *mapnp)
{
  Hashval mapn = *mapnp;
  Hashval newn = (mapn + 1) * 2 - 1;
  Hashval i, h, hh;
  Hashtable m;
  Id hx, qx;

  m = solv_calloc(newn + 1, 2 * sizeof(Id));
  for (i = 0; i <= mapn; i++)
    {
      hx = map[2 * i];
      if (!hx)
	continue;
      h = hx & newn;
      hh = HASHCHAIN_START;
      for (;;)
	{
	  qx = m[2 * h];
	  if (!qx)
	    break;
	  h = HASHCHAIN_NEXT(h, hh, newn);
	}
      m[2 * h] = hx;
      m[2 * h + 1] = map[2 * i + 1];
    }
  solv_free(map);
  *mapnp = newn;
  return m;
}
Пример #5
0
HyReldep
reldep_create(Pool *pool, Id r_id)
{
    HyReldep reldep = solv_calloc(1, sizeof(*reldep));
    reldep->pool = pool;
    reldep->r_id = r_id;
    return reldep;
}
Пример #6
0
HyReldepList
reldeplist_from_queue(Pool *pool, Queue h)
{
    HyReldepList reldeplist = solv_calloc(1, sizeof(*reldeplist));
    reldeplist->pool = pool;
    queue_init_clone(&reldeplist->queue, &h);
    return reldeplist;
}
Пример #7
0
HyAdvisoryList
advisorylist_create(Pool *pool)
{
    HyAdvisoryList advisorylist = solv_calloc(1, sizeof(*advisorylist));
    advisorylist->pool = pool;
    queue_init(&advisorylist->queue);
    return advisorylist;
}
Пример #8
0
HyAdvisory
advisory_create(Pool *pool, Id a_id)
{
    HyAdvisory advisory = solv_calloc(1, sizeof(*advisory));
    advisory->pool = pool;
    advisory->a_id = a_id;
    return advisory;
}
Пример #9
0
HyReldepList
hy_reldeplist_create(HySack sack)
{
    HyReldepList reldeplist = solv_calloc(1, sizeof(*reldeplist));
    reldeplist->pool = sack_pool(sack);
    queue_init(&reldeplist->queue);
    return reldeplist;
}
Пример #10
0
Файл: repo.c Проект: Xake/hawkey
HyRepo
hy_repo_create(const char *name)
{
    assert(name);
    HyRepo repo = solv_calloc(1, sizeof(*repo));
    repo->nrefs = 1;
    hy_repo_set_string(repo, HY_REPO_NAME, name);
    return repo;
}
Пример #11
0
HyPackage
package_create(HySack sack, Id id)
{
    HyPackage pkg;

    pkg = solv_calloc(1, sizeof(*pkg));
    pkg->nrefs = 1;
    pkg->sack = sack;
    pkg->id = id;
    return pkg;
}
Пример #12
0
/*
 * we support three relations:
 *
 * a = b   both architectures a and b are treated as equivalent
 * a > b   a is considered a "better" architecture, the solver
 *         should change from a to b, but must not change from b to a
 * a : b   a is considered a "better" architecture, the solver
 *         must not change the architecture from a to b or b to a
 */
void
pool_setarchpolicy(Pool *pool, const char *arch)
{
  unsigned int score = 0x10001;
  size_t l;
  char d;
  Id *id2arch;
  Id id, lastarch;

  pool->id2arch = solv_free(pool->id2arch);
  pool->id2color = solv_free(pool->id2color);
  if (!arch)
    {
      pool->lastarch = 0;
      return;
    }
  id = pool->noarchid;
  lastarch = id + 255;
  /* note that we overallocate one element to be compatible with
   * old versions that accessed id2arch[lastarch].
   * id2arch[lastarch] will always be zero */
  id2arch = solv_calloc(lastarch + 1, sizeof(Id));
  id2arch[id] = 1;	/* the "noarch" class */

  d = 0;
  while (*arch)
    {
      l = strcspn(arch, ":=>");
      if (l)
	{
	  id = pool_strn2id(pool, arch, l, 1);
	  if (id >= lastarch)
	    {
	      id2arch = solv_realloc2(id2arch, (id + 255 + 1), sizeof(Id));
	      memset(id2arch + lastarch + 1, 0, (id + 255 - lastarch) * sizeof(Id));
	      lastarch = id + 255;
	    }
	  if (id2arch[id] == 0)
	    {
	      if (d == ':')
		score += 0x10000;
	      else if (d == '>')
		score += 0x00001;
	      id2arch[id] = score;
	    }
	}
      arch += l;
      if ((d = *arch++) == 0)
	break;
    }
  pool->id2arch = id2arch;
  pool->lastarch = lastarch;
}
Пример #13
0
void *
solv_chksum_create_from_bin(Id type, const unsigned char *buf)
{
    struct ctxhandle *h;
    int l = solv_chksum_len(type);
    if (buf == 0 || l == 0)
        return 0;
    h = solv_calloc(1, sizeof(*h));
    h->type = type;
    h->done = 1;
    memcpy(h->result, buf, l);
    return h;
}
Пример #14
0
Chksum *
solv_chksum_create_from_bin(Id type, const unsigned char *buf)
{
  Chksum *chk;
  int l = solv_chksum_len(type);
  if (buf == 0 || l == 0)
    return 0;
  chk = solv_calloc(1, sizeof(*chk));
  chk->type = type;
  chk->done = 1;
  memcpy(chk->result, buf, l);
  return chk;
}
Пример #15
0
/*
 * we support three relations:
 *
 * a = b   both architectures a and b are treated as equivalent
 * a > b   a is considered a "better" architecture, the solver
 *         should change from a to b, but must not change from b to a
 * a : b   a is considered a "better" architecture, the solver
 *         must not change the architecture from a to b or b to a
 */
void
pool_setarchpolicy(Pool *pool, const char *arch)
{
  unsigned int score = 0x10001;
  size_t l;
  char d;
  Id *id2arch;
  Id id, lastarch;

  pool->id2arch = solv_free(pool->id2arch);
  pool->id2color = solv_free(pool->id2color);
  if (!arch)
    {
      pool->lastarch = 0;
      return;
    }
  id = pool->noarchid;
  lastarch = id + 255;
  id2arch = solv_calloc(lastarch + 1, sizeof(Id));
  id2arch[id] = 1;	/* the "noarch" class */

  d = 0;
  while (*arch)
    {
      l = strcspn(arch, ":=>");
      if (l)
	{
	  id = pool_strn2id(pool, arch, l, 1);
	  if (id > lastarch)
	    {
	      id2arch = solv_realloc2(id2arch, (id + 255 + 1), sizeof(Id));
	      memset(id2arch + lastarch + 1, 0, (id + 255 - lastarch) * sizeof(Id));
	      lastarch = id + 255;
	    }
	  if (id2arch[id] == 0)
	    {
	      if (d == ':')
		score += 0x10000;
	      else if (d == '>')
		score += 0x00001;
	      id2arch[id] = score;
	    }
	}
      arch += l;
      if ((d = *arch++) == 0)
	break;
    }
  pool->id2arch = id2arch;
  pool->lastarch = lastarch;
}
Пример #16
0
Repo *
repo_create(Pool *pool, const char *name)
{
  Repo *repo;

  pool_freewhatprovides(pool);
  repo = (Repo *)solv_calloc(1, sizeof(*repo));
  if (!pool->nrepos)
    {
      pool->nrepos = 1;	/* start with repoid 1 */
      pool->repos = (Repo **)solv_calloc(2, sizeof(Repo *));
    }
  else
    pool->repos = (Repo **)solv_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *));
  pool->repos[pool->nrepos] = repo;
  pool->urepos++;
  repo->repoid = pool->nrepos++;
  repo->name = name ? solv_strdup(name) : 0;
  repo->pool = pool;
  repo->start = pool->nsolvables;
  repo->end = pool->nsolvables;
  repo->nsolvables = 0;
  return repo;
}
static Hashtable
joinhash_init(Repo *repo, Hashval *hmp)
{
  Hashval hm = mkmask(repo->nsolvables);
  Hashtable ht = solv_calloc(hm + 1, sizeof(*ht));
  Hashval h, hh;
  Solvable *s;
  int i;

  FOR_REPO_SOLVABLES(repo, i, s)
    {
      hh = HASHCHAIN_START;
      h = s->name & hm;
      while (ht[h])
        h = HASHCHAIN_NEXT(h, hh, hm);
      ht[h] = i;
    }
Пример #18
0
unsigned char
pool_arch2color_slow(Pool *pool, Id arch)
{
  const char *s;
  unsigned char color;

  if (arch > pool->lastarch)
    return ARCHCOLOR_ALL;
  if (!pool->id2color)
    pool->id2color = solv_calloc(pool->lastarch + 1, 1);
  s = pool_id2str(pool, arch);
  if (arch == ARCH_NOARCH || arch == ARCH_ALL || arch == ARCH_ANY)
    color = ARCHCOLOR_ALL;
  else if (!strcmp(s, "s390x") || strstr(s, "64"))
    color = ARCHCOLOR_64;
  else
    color = ARCHCOLOR_32;
  pool->id2color[arch] = color;
  return color;
}
Пример #19
0
void *
solv_chksum_create(Id type)
{
    struct ctxhandle *h;
    h = solv_calloc(1, sizeof(*h));
    h->type = type;
    switch(type)
    {
    case REPOKEY_TYPE_MD5:
        solv_MD5_Init(&h->c.md5);
        return h;
    case REPOKEY_TYPE_SHA1:
        solv_SHA1_Init(&h->c.sha1);
        return h;
    case REPOKEY_TYPE_SHA256:
        solv_SHA256_Init(&h->c.sha256);
        return h;
    default:
        break;
    }
    free(h);
    return 0;
}
Пример #20
0
void
pool_setvendorclasses(Pool *pool, const char **vendorclasses)
{
  int i;
  const char **v;

  if (pool->vendorclasses)
    {
      for (v = pool->vendorclasses; v[0] || v[1]; v++)
	solv_free((void *)*v);
      pool->vendorclasses = solv_free((void *)pool->vendorclasses);
    }
  if (!vendorclasses || !vendorclasses[0])
    return;
  for (v = vendorclasses; v[0] || v[1]; v++)
    ;
  pool->vendorclasses = solv_calloc(v - vendorclasses + 2, sizeof(const char *));
  for (v = vendorclasses, i = 0; v[0] || v[1]; v++, i++)
    pool->vendorclasses[i] = *v ? solv_strdup(*v) : 0;
  pool->vendorclasses[i++] = 0;
  pool->vendorclasses[i] = 0;
  queue_empty(&pool->vendormap);
}
Пример #21
0
void
sack_recompute_considered(HySack sack)
{
    Pool *pool = sack_pool(sack);
    if (sack->considered_uptodate)
	return;
    if (!pool->considered) {
	if (!sack->repo_excludes && !sack->pkg_excludes)
	    return;
	pool->considered = solv_calloc(1, sizeof(Map));
	map_init(pool->considered, pool->nsolvables);
    } else
	map_grow(pool->considered, pool->nsolvables);

    // considered = (all - repo_excludes - pkg_excludes) and pkg_includes
    map_setall(pool->considered);
    if (sack->repo_excludes)
	map_subtract(pool->considered, sack->repo_excludes);
    if (sack->pkg_excludes)
	map_subtract(pool->considered, sack->pkg_excludes);
    if (sack->pkg_includes)
	map_and(pool->considered, sack->pkg_includes);
    sack->considered_uptodate = 1;
}
Пример #22
0
 * bitmap.c
 *
 */

#include <stdlib.h>
#include <string.h>

#include "bitmap.h"
#include "util.h"

/* constructor */
void
map_init(Map *m, int n)
{
  m->size = (n + 7) >> 3;
  m->map = m->size ? solv_calloc(m->size, 1) : 0;
}

/* destructor */
void
map_free(Map *m)
{
  m->map = solv_free(m->map);
  m->size = 0;
}

/* copy constructor t <- s */
void
map_init_clone(Map *t, Map *s)
{
  t->size = s->size;
Пример #23
0
int
main(int argc, char **argv)
{
  Pool *pool;
  Repo *commandlinerepo = 0;
  Id *commandlinepkgs = 0;
  Id p;
  struct repoinfo *repoinfos, installedrepoinfo;
  int nrepoinfos = 0;
  int mainmode = 0, mode = 0;
  int i, newpkgs;
  Queue job, checkq;
  Solver *solv = 0;
  Transaction *trans;
  FILE **newpkgsfps;
  Queue repofilter;
  Queue kindfilter;
  Queue archfilter;
  int archfilter_src = 0;
  int cleandeps = 0;
  int forcebest = 0;
  char *rootdir = 0;
  char *keyname = 0;
  int keyname_depstr = 0;
  int debuglevel = 0;
  int answer, acnt = 0;

  argc--;
  argv++;
  while (argc && !strcmp(argv[0], "-d"))
    {
      debuglevel++;
      argc--;
      argv++;
    }
  if (!argv[0])
    usage(1);
  if (!strcmp(argv[0], "install") || !strcmp(argv[0], "in"))
    {
      mainmode = MODE_INSTALL;
      mode = SOLVER_INSTALL;
    }
#if defined(SUSE) || defined(FEDORA)
  else if (!strcmp(argv[0], "patch"))
    {
      mainmode = MODE_PATCH;
      mode = SOLVER_INSTALL;
    }
#endif
  else if (!strcmp(argv[0], "erase") || !strcmp(argv[0], "rm"))
    {
      mainmode = MODE_ERASE;
      mode = SOLVER_ERASE;
    }
  else if (!strcmp(argv[0], "list") || !strcmp(argv[0], "ls"))
    {
      mainmode = MODE_LIST;
      mode = 0;
    }
  else if (!strcmp(argv[0], "info"))
    {
      mainmode = MODE_INFO;
      mode = 0;
    }
  else if (!strcmp(argv[0], "search") || !strcmp(argv[0], "se"))
    {
      mainmode = MODE_SEARCH;
      mode = 0;
    }
  else if (!strcmp(argv[0], "verify"))
    {
      mainmode = MODE_VERIFY;
      mode = SOLVER_VERIFY;
    }
  else if (!strcmp(argv[0], "update") || !strcmp(argv[0], "up"))
    {
      mainmode = MODE_UPDATE;
      mode = SOLVER_UPDATE;
    }
  else if (!strcmp(argv[0], "dist-upgrade") || !strcmp(argv[0], "dup"))
    {
      mainmode = MODE_DISTUPGRADE;
      mode = SOLVER_DISTUPGRADE;
    }
  else if (!strcmp(argv[0], "repos") || !strcmp(argv[0], "repolist") || !strcmp(argv[0], "lr"))
    {
      mainmode = MODE_REPOLIST;
      mode = 0;
    }
  else
    usage(1);

  for (;;)
    {
      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 if (argc > 1 && !strcmp(argv[1], "--best"))
	{
	  forcebest = 1;
	  argc--;
	  argv++;
	}
      else if (argc > 1 && !strcmp(argv[1], "--depstr"))
	{
	  keyname_depstr = 1;
	  argc--;
	  argv++;
	}
      else if (argc > 2 && !strcmp(argv[1], "--keyname"))
	{
	  keyname = argv[2];
	  argc -= 2;
	  argv += 2;
	}
      else
	break;
    }

  set_userhome();
  pool = pool_create();
  pool_set_rootdir(pool, rootdir);

#if 0
  {
    const char *langs[] = {"de_DE", "de", "en"};
    pool_set_languages(pool, langs, sizeof(langs)/sizeof(*langs));
  }
#endif

  pool_setloadcallback(pool, load_stub, 0);
#ifdef SUSE
  pool->nscallback = nscallback;
#endif
  if (debuglevel)
    pool_setdebuglevel(pool, debuglevel);
  setarch(pool);
  pool_set_flag(pool, POOL_FLAG_ADDFILEPROVIDESFILTERED, 1);
  repoinfos = read_repoinfos(pool, &nrepoinfos);
  sort_repoinfos(repoinfos, nrepoinfos);

  if (mainmode == MODE_REPOLIST)
    {
      int j = 1;
      for (i = 0; i < nrepoinfos; i++)
	{
	  struct repoinfo *cinfo = repoinfos + i;
	  if (!cinfo->enabled)
	    continue;
	  printf("%d: %-20s %s (prio %d)\n", j++, cinfo->alias, cinfo->name, cinfo->priority);
	}
      exit(0);
    }
  memset(&installedrepoinfo, 0, sizeof(installedrepoinfo));
  if (!read_installed_repo(&installedrepoinfo, pool))
    exit(1);
  read_repos(pool, repoinfos, nrepoinfos);

  /* setup filters */
  queue_init(&repofilter);
  queue_init(&kindfilter);
  queue_init(&archfilter);
  while (argc > 1)
    {
      if (!strcmp(argv[1], "-i"))
	{
	  queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO, pool->installed->repoid);
	  argc--;
	  argv++;
	}
      else if (argc > 2 && (!strcmp(argv[1], "-r") || !strcmp(argv[1], "--repo")))
	{
	  Id repoid = find_repo(argv[2], pool, repoinfos, nrepoinfos);
	  if (!repoid)
	    {
	      fprintf(stderr, "%s: no such repo\n", argv[2]);
	      exit(1);
	    }
	  /* SETVENDOR is actually wrong but useful */
	  queue_push2(&repofilter, SOLVER_SOLVABLE_REPO | SOLVER_SETREPO | SOLVER_SETVENDOR, repoid);
	  argc -= 2;
	  argv += 2;
	}
      else if (argc > 2 && !strcmp(argv[1], "--arch"))
	{
	  if (!strcmp(argv[2], "src") || !strcmp(argv[2], "nosrc"))
	    archfilter_src = 1;
	  queue_push2(&archfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, pool_str2id(pool, argv[2], 1), REL_ARCH, 1));
	  argc -= 2;
	  argv += 2;
	}
      else if (argc > 2 && (!strcmp(argv[1], "-t") || !strcmp(argv[1], "--type")))
	{
	  const char *kind = argv[2];
	  if (!strcmp(kind, "srcpackage"))
	    {
	      /* hey! should use --arch! */
	      queue_push2(&archfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, ARCH_SRC, REL_ARCH, 1));
	      archfilter_src = 1;
	      argc -= 2;
	      argv += 2;
	      continue;
	    }
	  if (!strcmp(kind, "package"))
	    kind = "";
	  if (!strcmp(kind, "all"))
	    queue_push2(&kindfilter, SOLVER_SOLVABLE_ALL, 0);
	  else
	    queue_push2(&kindfilter, SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, 0, pool_str2id(pool, kind, 1), REL_KIND, 1));
	  argc -= 2;
	  argv += 2;
	}
      else
	break;
    }

  if (mainmode == MODE_SEARCH)
    {
      Queue sel, q;
      Dataiterator di;
      if (argc != 2)
	usage(1);
      pool_createwhatprovides(pool);
      queue_init(&sel);
      dataiterator_init(&di, pool, 0, 0, 0, argv[1], SEARCH_SUBSTRING|SEARCH_NOCASE);
      dataiterator_set_keyname(&di, SOLVABLE_NAME);
      dataiterator_set_search(&di, 0, 0);
      while (dataiterator_step(&di))
	queue_push2(&sel, SOLVER_SOLVABLE, di.solvid);
      dataiterator_set_keyname(&di, SOLVABLE_SUMMARY);
      dataiterator_set_search(&di, 0, 0);
      while (dataiterator_step(&di))
	queue_push2(&sel, SOLVER_SOLVABLE, di.solvid);
      dataiterator_set_keyname(&di, SOLVABLE_DESCRIPTION);
      dataiterator_set_search(&di, 0, 0);
      while (dataiterator_step(&di))
	queue_push2(&sel, SOLVER_SOLVABLE, di.solvid);
      dataiterator_free(&di);
      if (repofilter.count)
	selection_filter(pool, &sel, &repofilter);
	
      queue_init(&q);
      selection_solvables(pool, &sel, &q);
      queue_free(&sel);
      for (i = 0; i < q.count; i++)
	{
	  Solvable *s = pool_id2solvable(pool, q.elements[i]);
	  printf("  - %s [%s]: %s\n", pool_solvable2str(pool, s), s->repo->name, solvable_lookup_str(s, SOLVABLE_SUMMARY));
	}
      queue_free(&q);
      exit(0);
    }

  /* process command line packages */
  if (mainmode == MODE_LIST || mainmode == MODE_INFO || mainmode == MODE_INSTALL)
    {
      for (i = 1; i < argc; i++)
	{
	  if (!is_cmdline_package((const char *)argv[i]))
	    continue;
	  if (access(argv[i], R_OK))
	    {
	      perror(argv[i]);
	      exit(1);
	    }
	  if (!commandlinepkgs)
	    commandlinepkgs = solv_calloc(argc, sizeof(Id));
	  if (!commandlinerepo)
	    commandlinerepo = repo_create(pool, "@commandline");
	  p = add_cmdline_package(commandlinerepo, (const char *)argv[i]);
	  if (!p)
	    {
	      fprintf(stderr, "could not add '%s'\n", argv[i]);
	      exit(1);
	    }
	  commandlinepkgs[i] = p;
	}
      if (commandlinerepo)
	repo_internalize(commandlinerepo);
    }

#if defined(ENABLE_RPMDB)
  if (pool->disttype == DISTTYPE_RPM)
    addfileprovides(pool);
#endif
#ifdef SUSE
  add_autopackages(pool);
#endif
  pool_createwhatprovides(pool);

  if (keyname)
    keyname = solv_dupjoin("solvable:", keyname, 0);
  queue_init(&job);
  for (i = 1; i < argc; i++)
    {
      Queue job2;
      int flags, rflags;

      if (commandlinepkgs && commandlinepkgs[i])
	{
	  queue_push2(&job, SOLVER_SOLVABLE, commandlinepkgs[i]);
	  continue;
	}
      queue_init(&job2);
      flags = SELECTION_NAME|SELECTION_PROVIDES|SELECTION_GLOB;
      flags |= SELECTION_CANON|SELECTION_DOTARCH|SELECTION_REL;
      if (kindfilter.count)
	flags |= SELECTION_SKIP_KIND;
      if (mode == MODE_LIST || archfilter_src)
	flags |= SELECTION_WITH_SOURCE;
      if (argv[i][0] == '/')
	flags |= SELECTION_FILELIST | (mode == MODE_ERASE ? SELECTION_INSTALLED_ONLY : 0);
      if (!keyname)
        rflags = selection_make(pool, &job2, argv[i], flags);
      else
	{
	  if (keyname_depstr)
	    flags |= SELECTION_MATCH_DEPSTR;
          rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0);
	}
      if (repofilter.count)
	selection_filter(pool, &job2, &repofilter);
      if (archfilter.count)
	selection_filter(pool, &job2, &archfilter);
      if (kindfilter.count)
	selection_filter(pool, &job2, &kindfilter);
      if (!job2.count)
	{
	  flags |= SELECTION_NOCASE;
	  if (!keyname)
            rflags = selection_make(pool, &job2, argv[i], flags);
	  else
	    rflags = selection_make_matchdeps(pool, &job2, argv[i], flags, pool_str2id(pool, keyname, 1), 0);
	  if (repofilter.count)
	    selection_filter(pool, &job2, &repofilter);
	  if (archfilter.count)
	    selection_filter(pool, &job2, &archfilter);
	  if (kindfilter.count)
	    selection_filter(pool, &job2, &kindfilter);
	  if (job2.count)
	    printf("[ignoring case for '%s']\n", argv[i]);
	}
      if (!job2.count)
	{
	  fprintf(stderr, "nothing matches '%s'\n", argv[i]);
	  exit(1);
	}
      if (rflags & SELECTION_FILELIST)
        printf("[using file list match for '%s']\n", argv[i]);
      if (rflags & SELECTION_PROVIDES)
	printf("[using capability match for '%s']\n", argv[i]);
      queue_insertn(&job, job.count, job2.count, job2.elements);
      queue_free(&job2);
    }
  keyname = solv_free(keyname);

  if (!job.count && (mainmode == MODE_UPDATE || mainmode == MODE_DISTUPGRADE || mainmode == MODE_VERIFY || repofilter.count || archfilter.count || kindfilter.count))
    {
      queue_push2(&job, SOLVER_SOLVABLE_ALL, 0);
      if (repofilter.count)
	selection_filter(pool, &job, &repofilter);
      if (archfilter.count)
	selection_filter(pool, &job, &archfilter);
      if (kindfilter.count)
	selection_filter(pool, &job, &kindfilter);
    }
  queue_free(&repofilter);
  queue_free(&archfilter);
  queue_free(&kindfilter);

  if (!job.count && mainmode != MODE_PATCH)
    {
      printf("no package matched\n");
      exit(1);
    }

  if (mainmode == MODE_LIST || mainmode == MODE_INFO)
    {
      /* list mode, no solver needed */
      Queue q;
      queue_init(&q);
      for (i = 0; i < job.count; i += 2)
	{
	  int j;
	  queue_empty(&q);
	  pool_job2solvables(pool, &q, job.elements[i], job.elements[i + 1]);
	  for (j = 0; j < q.count; j++)
	    {
	      Solvable *s = pool_id2solvable(pool, q.elements[j]);
	      if (mainmode == MODE_INFO)
		{
		  const char *str;
		  printf("Name:        %s\n", pool_solvable2str(pool, s));
		  printf("Repo:        %s\n", s->repo->name);
		  printf("Summary:     %s\n", solvable_lookup_str(s, SOLVABLE_SUMMARY));
		  str = solvable_lookup_str(s, SOLVABLE_URL);
		  if (str)
		    printf("Url:         %s\n", str);
		  str = solvable_lookup_str(s, SOLVABLE_LICENSE);
		  if (str)
		    printf("License:     %s\n", str);
		  printf("Description:\n%s\n", solvable_lookup_str(s, SOLVABLE_DESCRIPTION));
		  printf("\n");
		}
	      else
		{
#if 1
		  const char *sum = solvable_lookup_str_lang(s, SOLVABLE_SUMMARY, "de", 1);
#else
		  const char *sum = solvable_lookup_str_poollang(s, SOLVABLE_SUMMARY);
#endif
		  printf("  - %s [%s]\n", pool_solvable2str(pool, s), s->repo->name);
		  if (sum)
		    printf("    %s\n", sum);
		}
	    }
	}
      queue_free(&q);
      queue_free(&job);
      pool_free(pool);
      free_repoinfos(repoinfos, nrepoinfos);
      solv_free(commandlinepkgs);
      exit(0);
    }

#if defined(SUSE) || defined(FEDORA)
  if (mainmode == MODE_PATCH)
    add_patchjobs(pool, &job);
#endif

  // add mode
  for (i = 0; i < job.count; i += 2)
    {
      job.elements[i] |= mode;
      if (mode == SOLVER_UPDATE && pool_isemptyupdatejob(pool, job.elements[i], job.elements[i + 1]))
	job.elements[i] ^= SOLVER_UPDATE ^ SOLVER_INSTALL;
      if (cleandeps)
        job.elements[i] |= SOLVER_CLEANDEPS;
      if (forcebest)
        job.elements[i] |= SOLVER_FORCEBEST;
    }

  // multiversion test
  // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae", 1));
  // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-base", 1));
  // queue_push2(&job, SOLVER_MULTIVERSION|SOLVER_SOLVABLE_NAME, pool_str2id(pool, "kernel-pae-extra", 1));
#if 0
  queue_push2(&job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
  queue_push2(&job, SOLVER_ERASE|SOLVER_CLEANDEPS|SOLVER_SOLVABLE_PROVIDES, pool_rel2id(pool, NAMESPACE_LANGUAGE, 0, REL_NAMESPACE, 1));
#endif

rerunsolver:
  solv = solver_create(pool);
  solver_set_flag(solv, SOLVER_FLAG_SPLITPROVIDES, 1);
#ifdef FEDORA
  solver_set_flag(solv, SOLVER_FLAG_ALLOW_VENDORCHANGE, 1);
#endif
  if (mainmode == MODE_ERASE)
    solver_set_flag(solv, SOLVER_FLAG_ALLOW_UNINSTALL, 1);	/* don't nag */
  solver_set_flag(solv, SOLVER_FLAG_BEST_OBEY_POLICY, 1);

  for (;;)
    {
      Id problem, solution;
      int pcnt, scnt;

      if (!solver_solve(solv, &job))
	break;
      pcnt = solver_problem_count(solv);
      printf("Found %d problems:\n", pcnt);
      for (problem = 1; problem <= pcnt; problem++)
	{
	  int take = 0;
	  printf("Problem %d/%d:\n", problem, pcnt);
	  solver_printprobleminfo(solv, problem);
	  printf("\n");
	  scnt = solver_solution_count(solv, problem);
	  for (solution = 1; solution <= scnt; solution++)
	    {
	      printf("Solution %d:\n", solution);
	      solver_printsolution(solv, problem, solution);
	      printf("\n");
	    }
	  for (;;)
	    {
	      char inbuf[128], *ip;
	      printf("Please choose a solution: ");
	      fflush(stdout);
	      *inbuf = 0;
	      if (!(ip = fgets(inbuf, sizeof(inbuf), stdin)))
		{
		  printf("Abort.\n");
		  exit(1);
		}
	      while (*ip == ' ' || *ip == '\t')
		ip++;
	      if (*ip >= '0' && *ip <= '9')
		{
		  take = atoi(ip);
		  if (take >= 1 && take <= scnt)
		    break;
		}
	      if (*ip == 's')
		{
		  take = 0;
		  break;
		}
	      if (*ip == 'q')
		{
		  printf("Abort.\n");
		  exit(1);
		}
	    }
	  if (!take)
	    continue;
	  solver_take_solution(solv, problem, take, &job);
	}
    }

  trans = solver_create_transaction(solv);
  if (!trans->steps.count)
    {
      printf("Nothing to do.\n");
      transaction_free(trans);
      solver_free(solv);
      queue_free(&job);
      pool_free(pool);
      free_repoinfos(repoinfos, nrepoinfos);
      solv_free(commandlinepkgs);
      exit(1);
    }

  /* display transaction to the user and ask for confirmation */
  printf("\n");
  printf("Transaction summary:\n\n");
  transaction_print(trans);
#if defined(SUSE)
  showdiskusagechanges(trans);
#endif
  printf("install size change: %d K\n", transaction_calc_installsizechange(trans));
  printf("\n");

  acnt = solver_alternatives_count(solv);
  if (acnt)
    {
      if (acnt == 1)
        printf("Have one alternative:\n");
      else
        printf("Have %d alternatives:\n", acnt);
      for (i = 1; i <= acnt; i++)
	{
	  Id id, from;
	  int atype = solver_get_alternative(solv, i, &id, &from, 0, 0, 0);
	  printf("  - %s\n", solver_alternative2str(solv, atype, id, from));
	}
      printf("\n");
      answer = yesno("OK to continue (y/n/a)? ", 'a');
    }
  else
    answer = yesno("OK to continue (y/n)? ", 0);
  if (answer == 'a')
    {
      Queue choicesq;
      Queue answerq;
      Id id, from, chosen;
      int j;

      queue_init(&choicesq);
      queue_init(&answerq);
      for (i = 1; i <= acnt; i++)
	{
	  int atype = solver_get_alternative(solv, i, &id, &from, &chosen, &choicesq, 0);
	  printf("\n%s\n", solver_alternative2str(solv, atype, id, from));
	  for (j = 0; j < choicesq.count; j++)
	    {
	      Id p = choicesq.elements[j];
	      if (p < 0)
		p = -p;
	      queue_push(&answerq, p);
	      printf("%6d: %s\n", answerq.count, pool_solvid2str(pool, p));
	    }
	}
      queue_free(&choicesq);
      printf("\n");
      for (;;)
	{
	  char inbuf[128], *ip;
	  int neg = 0;
	  printf("OK to continue (y/n), or number to change alternative: ");
	  fflush(stdout);
	  *inbuf = 0;
	  if (!(ip = fgets(inbuf, sizeof(inbuf), stdin)))
	    {
	      printf("Abort.\n");
	      exit(1);
	    }
	  while (*ip == ' ' || *ip == '\t')
	    ip++;
	  if (*ip == '-' && ip[1] >= '0' && ip[1] <= '9')
	    {
	      neg = 1;
	      ip++;
	    }
	  if (*ip >= '0' && *ip <= '9')
	    {
	      int take = atoi(ip);
	      if (take > 0 && take <= answerq.count)
		{
		  Id p = answerq.elements[take - 1];
		  queue_free(&answerq);
		  queue_push2(&job, (neg ? SOLVER_DISFAVOR : SOLVER_FAVOR) | SOLVER_SOLVABLE_NAME, pool->solvables[p].name);
		  solver_free(solv);
		  solv = 0;
		  goto rerunsolver;
		  break;
		}
	    }
	  if (*ip == 'n' || *ip == 'y')
	    {
	      answer = *ip == 'n' ? 0 : *ip;
	      break;
	    }
	}
      queue_free(&answerq);
    }
  if (!answer)
    {
      printf("Abort.\n");
      transaction_free(trans);
      solver_free(solv);
      queue_free(&job);
      pool_free(pool);
      free_repoinfos(repoinfos, nrepoinfos);
      solv_free(commandlinepkgs);
      exit(1);
    }

  /* download all new packages */
  queue_init(&checkq);
  newpkgs = transaction_installedresult(trans, &checkq);
  newpkgsfps = 0;
  if (newpkgs)
    {
      int downloadsize = 0;
      for (i = 0; i < newpkgs; i++)
	{
	  Solvable *s;

	  p = checkq.elements[i];
	  s = pool_id2solvable(pool, p);
	  downloadsize += solvable_lookup_sizek(s, SOLVABLE_DOWNLOADSIZE, 0);
	}
      printf("Downloading %d packages, %d K\n", newpkgs, downloadsize);
      newpkgsfps = solv_calloc(newpkgs, sizeof(*newpkgsfps));
      for (i = 0; i < newpkgs; i++)
	{
	  const char *loc;
	  Solvable *s;
	  struct repoinfo *cinfo;

	  p = checkq.elements[i];
	  s = pool_id2solvable(pool, p);
	  if (s->repo == commandlinerepo)
	    {
	      loc = solvable_lookup_location(s, 0);
	      if (!loc)
		continue;
	      if (!(newpkgsfps[i] = fopen(loc, "r")))
		{
		  perror(loc);
		  exit(1);
		}
	      putchar('.');
	      continue;
	    }
	  cinfo = s->repo->appdata;
	  if (!cinfo || cinfo->type == TYPE_INSTALLED)
	    {
	      printf("%s: no repository information\n", s->repo->name);
	      exit(1);
	    }
	  loc = solvable_lookup_location(s, 0);
	  if (!loc)
	     continue;	/* pseudo package? */
#if defined(ENABLE_RPMDB)
	  if (pool->installed && pool->installed->nsolvables)
	    {
	      if ((newpkgsfps[i] = trydeltadownload(s, loc)) != 0)
		{
		  putchar('d');
		  fflush(stdout);
		  continue;		/* delta worked! */
		}
	    }
#endif
	  if ((newpkgsfps[i] = downloadpackage(s, loc)) == 0)
	    {
	      printf("\n%s: %s not found in repository\n", s->repo->name, loc);
	      exit(1);
	    }
	  putchar('.');
	  fflush(stdout);
	}
      putchar('\n');
    }

#if defined(ENABLE_RPMDB) && (defined(SUSE) || defined(FEDORA) || defined(MANDRIVA) || defined(MAGEIA))
  /* check for file conflicts */
  if (newpkgs)
    {
      Queue conflicts;
      queue_init(&conflicts);
      if (checkfileconflicts(pool, &checkq, newpkgs, newpkgsfps, &conflicts))
	{
	  if (yesno("Re-run solver (y/n/q)? ", 0))
	    {
	      for (i = 0; i < newpkgs; i++)
		if (newpkgsfps[i])
		  fclose(newpkgsfps[i]);
	      newpkgsfps = solv_free(newpkgsfps);
	      solver_free(solv);
	      solv = 0;
	      pool_add_fileconflicts_deps(pool, &conflicts);
	      queue_free(&conflicts);
	      goto rerunsolver;
	    }
	}
      queue_free(&conflicts);
    }
#endif

  /* and finally commit the transaction */
  printf("Committing transaction:\n\n");
  transaction_order(trans, 0);
  for (i = 0; i < trans->steps.count; i++)
    {
      int j;
      FILE *fp;
      Id type;

      p = trans->steps.elements[i];
      type = transaction_type(trans, p, SOLVER_TRANSACTION_RPM_ONLY);
      switch(type)
	{
	case SOLVER_TRANSACTION_ERASE:
	  printf("erase %s\n", pool_solvid2str(pool, p));
	  commit_transactionelement(pool, type, p, 0);
	  break;
	case SOLVER_TRANSACTION_INSTALL:
	case SOLVER_TRANSACTION_MULTIINSTALL:
	  printf("install %s\n", pool_solvid2str(pool, p));
	  for (j = 0; j < newpkgs; j++)
	    if (checkq.elements[j] == p)
	      break;
	  fp = j < newpkgs ? newpkgsfps[j] : 0;
	  if (!fp)
	    continue;
	  commit_transactionelement(pool, type, p, fp);
	  fclose(fp);
	  newpkgsfps[j] = 0;
	  break;
	default:
	  break;
	}
    }

  for (i = 0; i < newpkgs; i++)
    if (newpkgsfps[i])
      fclose(newpkgsfps[i]);
  solv_free(newpkgsfps);
  queue_free(&checkq);
  transaction_free(trans);
  solver_free(solv);
  queue_free(&job);
  pool_free(pool);
  free_repoinfos(repoinfos, nrepoinfos);
  solv_free(commandlinepkgs);
  exit(0);
}
Пример #24
0
int
pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, int flags, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata)
{
  int i, j, cflmapn, idxmapset;
  struct cbdata cbdata;
  unsigned int now, start;
  void *handle;
  Repo *installed = pool->installed;
  Id p;
  int obsoleteusescolors = pool_get_flag(pool, POOL_FLAG_OBSOLETEUSESCOLORS);
  int hdrfetches;

  queue_empty(conflicts);
  if (!pkgs->count)
    return 0;

  now = start = solv_timems(0);
  POOL_DEBUG(SOLV_DEBUG_STATS, "searching for file conflicts\n");
  POOL_DEBUG(SOLV_DEBUG_STATS, "packages: %d, cutoff %d\n", pkgs->count, cutoff);

  memset(&cbdata, 0, sizeof(cbdata));
  cbdata.aliases = flags & FINDFILECONFLICTS_CHECK_DIRALIASING;
  cbdata.pool = pool;
  if (cbdata.aliases && (flags & FINDFILECONFLICTS_USE_ROOTDIR) != 0)
    {
      cbdata.rootdir = pool_get_rootdir(pool);
      if (cbdata.rootdir && !strcmp(cbdata.rootdir, "/"))
	cbdata.rootdir = 0;
      if (cbdata.rootdir)
	cbdata.rootdirl = strlen(cbdata.rootdir);
      if (!cbdata.rootdir)
	cbdata.usestat = 1;
    }
  queue_init(&cbdata.lookat);
  queue_init(&cbdata.lookat_dir);
  map_init(&cbdata.idxmap, pkgs->count);

  if (cutoff <= 0)
    cutoff = pkgs->count;

  /* avarage file list size: 200 files per package */
  /* avarage dir count: 20 dirs per package */

  /* first pass: scan dirs */
  if (!cbdata.aliases)
    {
      hdrfetches = 0;
      cflmapn = (cutoff + 3) * 64;
      while ((cflmapn & (cflmapn - 1)) != 0)
	cflmapn = cflmapn & (cflmapn - 1);
      cbdata.dirmap = solv_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++)
	{
	  if (i == cutoff)
	    cbdata.create = 0;
	  cbdata.idx = i;
	  p = pkgs->elements[i];
	  if ((flags & FINDFILECONFLICTS_USE_SOLVABLEFILELIST) != 0 && installed)
	    {
	      if (p >= installed->start && p < installed->end && pool->solvables[p].repo == installed)
		{
		  iterate_solvable_dirs(pool, p, finddirs_cb, &cbdata);
		  if (MAPTST(&cbdata.idxmap, i))
		    idxmapset++;
		  continue;
		}
	    }
	  handle = (*handle_cb)(pool, p, handle_cbdata);
	  if (!handle)
	    continue;
	  hdrfetches++;
	  rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata);
	  if (MAPTST(&cbdata.idxmap, i))
	    idxmapset++;
	}
      POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap size: %d, used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused);
      POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024);
      POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
      POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap creation took %d ms\n", solv_timems(now));
      POOL_DEBUG(SOLV_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count);
    }

  /* second pass: scan files */
  now = solv_timems(0);
  cflmapn = (cutoff + 3) * 128;
  while ((cflmapn & (cflmapn - 1)) != 0)
    cflmapn = cflmapn & (cflmapn - 1);
  cbdata.cflmap = solv_calloc(cflmapn, 2 * sizeof(Id));
  cbdata.cflmapn = cflmapn - 1;	/* make it a mask */
  cbdata.create = 1;
  hdrfetches = 0;
  for (i = 0; i < pkgs->count; i++)
    {
      if (i == cutoff)
	cbdata.create = 0;
      if (!cbdata.aliases && !MAPTST(&cbdata.idxmap, i))
	continue;
      cbdata.idx = i;
      p = pkgs->elements[i];
      if (!cbdata.create && (flags & FINDFILECONFLICTS_USE_SOLVABLEFILELIST) != 0 && installed)
	{
	  if (p >= installed->start && p < installed->end && pool->solvables[p].repo == installed)
	    if (!precheck_solvable_files(&cbdata, pool, p))
	      continue;
	}
      /* can't use FINDFILECONFLICTS_USE_SOLVABLEFILELIST because we have to know if
       * the file is a directory or not */
      handle = (*handle_cb)(pool, p, handle_cbdata);
      if (!handle)
	continue;
      hdrfetches++;
      cbdata.lastdiridx = -1;
      rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, cbdata.aliases ? findfileconflicts_basename_cb : findfileconflicts_cb, &cbdata);
    }

  POOL_DEBUG(SOLV_DEBUG_STATS, "filemap size: %d, used %d\n", cbdata.cflmapn + 1, cbdata.cflmapused);
  POOL_DEBUG(SOLV_DEBUG_STATS, "filemap memory usage: %d K\n", (cbdata.cflmapn + 1) * 2 * (int)sizeof(Id) / 1024);
  POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
  POOL_DEBUG(SOLV_DEBUG_STATS, "filemap creation took %d ms\n", solv_timems(now));
  POOL_DEBUG(SOLV_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count);
  queue_free(&cbdata.lookat_dir);

  /* we need another pass for aliases */
  if (cbdata.aliases)
    {
      now = solv_timems(0);
      /* make sure the first offset is not zero */
      addfilesspace(&cbdata, 1);
      cflmapn = (cutoff + 3) * 16;
      while ((cflmapn & (cflmapn - 1)) != 0)
	cflmapn = cflmapn & (cflmapn - 1);
      cbdata.normap = solv_calloc(cflmapn, 2 * sizeof(Id));
      cbdata.normapn = cflmapn - 1;	/* make it a mask */
      if (cbdata.usestat)
	{
	  cbdata.statmap = solv_calloc(cflmapn, 2 * sizeof(Id));
	  cbdata.statmapn = cflmapn - 1;	/* make it a mask */
	}
      cbdata.create = 0;
      hdrfetches = 0;
      for (i = 0; i < pkgs->count; i++)
	{
	  if (!MAPTST(&cbdata.idxmap, i))
	    continue;
	  p = pkgs->elements[i];
	  cbdata.idx = i;
	  /* can't use FINDFILECONFLICTS_USE_SOLVABLEFILELIST because we have to know if
	   * the file is a directory or not */
	  handle = (*handle_cb)(pool, p, handle_cbdata);
	  if (!handle)
	    continue;
	  hdrfetches++;
	  cbdata.lastdiridx = -1;
	  rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, findfileconflicts_alias_cb, &cbdata);
	}
      POOL_DEBUG(SOLV_DEBUG_STATS, "normap size: %d, used %d\n", cbdata.normapn + 1, cbdata.normapused);
      POOL_DEBUG(SOLV_DEBUG_STATS, "normap memory usage: %d K\n", (cbdata.normapn + 1) * 2 * (int)sizeof(Id) / 1024);
      POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
      POOL_DEBUG(SOLV_DEBUG_STATS, "stats made: %d\n", cbdata.statsmade);
      if (cbdata.usestat)
	{
	  POOL_DEBUG(SOLV_DEBUG_STATS, "statmap size: %d, used %d\n", cbdata.statmapn + 1, cbdata.statmapused);
	  POOL_DEBUG(SOLV_DEBUG_STATS, "statmap memory usage: %d K\n", (cbdata.statmapn + 1) * 2 * (int)sizeof(Id) / 1024);
	}
      cbdata.statmap = solv_free(cbdata.statmap);
      cbdata.statmapn = 0;
      cbdata.canonspace = solv_free(cbdata.canonspace);
      cbdata.canonspacen = 0;
      POOL_DEBUG(SOLV_DEBUG_STATS, "alias processing took %d ms\n", solv_timems(now));
    }

  cbdata.dirmap = solv_free(cbdata.dirmap);
  cbdata.dirmapn = 0;
  cbdata.dirmapused = 0;
  cbdata.cflmap = solv_free(cbdata.cflmap);
  cbdata.cflmapn = 0;
  cbdata.cflmapused = 0;

  map_free(&cbdata.idxmap);

  /* sort and unify/prune */
  now = solv_timems(0);
  POOL_DEBUG(SOLV_DEBUG_STATS, "raw candidates: %d, pruning\n", cbdata.lookat.count / 4);
  solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_hx_cmp, pool);
  for (i = j = 0; i < cbdata.lookat.count; )
    {
      int first = 1;
      Id hx = cbdata.lookat.elements[i];
      Id idx = cbdata.lookat.elements[i + 1];
      Id dhx = cbdata.lookat.elements[i + 2];
      Id dirid = cbdata.lookat.elements[i + 3];
      i += 4;
      for (; i < cbdata.lookat.count && hx == cbdata.lookat.elements[i] && (dirid == cbdata.lookat.elements[i + 3] || dirid == -cbdata.lookat.elements[i + 3]); i += 4)
	{
	  if (idx == cbdata.lookat.elements[i + 1] && dhx == cbdata.lookat.elements[i + 2])
	    continue;	/* ignore duplicates */
	  if (first)
	    {
	      if (dirid < 0)
		continue;	/* all have a neg dirid */
	      cbdata.lookat.elements[j++] = hx;
	      cbdata.lookat.elements[j++] = idx;
	      cbdata.lookat.elements[j++] = dhx;
	      cbdata.lookat.elements[j++] = dirid;
	      first = 0;
	    }
	  idx = cbdata.lookat.elements[i + 1];
	  dhx = cbdata.lookat.elements[i + 2];
	  cbdata.lookat.elements[j++] = hx;
	  cbdata.lookat.elements[j++] = idx;
	  cbdata.lookat.elements[j++] = dhx;
	  cbdata.lookat.elements[j++] = dirid;
	}
    }
  queue_truncate(&cbdata.lookat, j);
  POOL_DEBUG(SOLV_DEBUG_STATS, "candidates now: %d\n", cbdata.lookat.count / 4);
  POOL_DEBUG(SOLV_DEBUG_STATS, "pruning took %d ms\n", solv_timems(now));

  /* third pass: collect file info for all files that match a hx */
  now = solv_timems(0);
  solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_idx_cmp, pool);
  queue_init(&cbdata.files);
  hdrfetches = 0;
  for (i = 0; i < cbdata.lookat.count; i += 4)
    {
      Id idx = cbdata.lookat.elements[i + 1];
      int iterflags = RPM_ITERATE_FILELIST_WITHMD5 | RPM_ITERATE_FILELIST_NOGHOSTS;
      if (obsoleteusescolors)
	iterflags |= RPM_ITERATE_FILELIST_WITHCOL;
      p = pkgs->elements[idx];
      handle = (*handle_cb)(pool, p, handle_cbdata);
      if (handle)
	hdrfetches++;
      for (;; i += 4)
	{
	  int fstart = cbdata.files.count;
	  queue_push(&cbdata.files, idx);
	  queue_push(&cbdata.files, 0);
	  cbdata.idx = idx;
	  cbdata.hx = cbdata.lookat.elements[i];
	  cbdata.dirhash = cbdata.lookat.elements[i + 2];
	  cbdata.dirid = cbdata.lookat.elements[i + 3];
	  cbdata.lastdiridx = -1;
	  if (handle)
	    rpm_iterate_filelist(handle, iterflags, findfileconflicts2_cb, &cbdata);
	  cbdata.files.elements[fstart + 1] = cbdata.files.count;
	  cbdata.lookat.elements[i + 1] = fstart;
	  if (i + 4 >= cbdata.lookat.count || cbdata.lookat.elements[i + 4 + 1] != idx)
	    break;
	}
    }
  POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches);
  POOL_DEBUG(SOLV_DEBUG_STATS, "file info fetching took %d ms\n", solv_timems(now));

  cbdata.normap = solv_free(cbdata.normap);
  cbdata.normapn = 0;

  /* forth pass: for each hx we have, compare all matching files against all other matching files */
  now = solv_timems(0);
  solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_hx_cmp, pool);
  for (i = 0; i < cbdata.lookat.count - 4; i += 4)
    {
      Id hx = cbdata.lookat.elements[i];
      Id pstart = cbdata.lookat.elements[i + 1];
      Id dirid = cbdata.lookat.elements[i + 3];
      Id pidx = cbdata.files.elements[pstart];
      Id pend = cbdata.files.elements[pstart + 1];
      if (cbdata.lookat.elements[i + 4] != hx)
	continue;	/* no package left with that hx */
      for (j = i + 4; j < cbdata.lookat.count && cbdata.lookat.elements[j] == hx && cbdata.lookat.elements[j + 3] == dirid; j += 4)
	{
	  Id qstart = cbdata.lookat.elements[j + 1];
	  Id qidx = cbdata.files.elements[qstart];
	  Id qend = cbdata.files.elements[qstart + 1];
	  int ii, jj;
	  if (pidx >= cutoff && qidx >= cutoff)
	    continue;	/* no conflicts between packages with idx >= cutoff */
          for (ii = pstart + 2; ii < pend; ii++)
	    for (jj = qstart + 2; jj < qend; jj++)
	      {
		char *fsi = (char *)cbdata.filesspace + cbdata.files.elements[ii];
		char *fsj = (char *)cbdata.filesspace + cbdata.files.elements[jj];
		if (cbdata.aliases)
		  {
		    /* compare just the basenames, the dirs match because of the dirid */
		    char *bsi = strrchr(fsi + 34, '/');
		    char *bsj = strrchr(fsj + 34, '/');
		    if (!bsi || !bsj)
		      continue;
		    if (strcmp(bsi, bsj))
		      continue;	/* different base names */
		  }
		else
		  {
		    if (strcmp(fsi + 34, fsj + 34))
		      continue;	/* different file names */
		  }
		if (!strcmp(fsi, fsj))
		  continue;	/* file digests match, no conflict */
		if (obsoleteusescolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0)
		  continue;	/* colors do not conflict */
		queue_push(conflicts, pool_str2id(pool, fsi + 34, 1));
		queue_push(conflicts, pkgs->elements[pidx]);
		queue_push(conflicts, pool_str2id(pool, fsi, 1));
		queue_push(conflicts, pool_str2id(pool, fsj + 34, 1));
		queue_push(conflicts, pkgs->elements[qidx]);
		queue_push(conflicts, pool_str2id(pool, fsj, 1));
	      }
	}
    }
  POOL_DEBUG(SOLV_DEBUG_STATS, "filespace size: %d K\n", cbdata.filesspacen / 1024);
  POOL_DEBUG(SOLV_DEBUG_STATS, "candidate check took %d ms\n", solv_timems(now));
  cbdata.filesspace = solv_free(cbdata.filesspace);
  cbdata.filesspacen = 0;
  queue_free(&cbdata.lookat);
  queue_free(&cbdata.files);
  if (conflicts->count > 6)
    solv_sort(conflicts->elements, conflicts->count / 6, 6 * sizeof(Id), conflicts_cmp, pool);
  POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file conflicts\n", conflicts->count / 6);
  POOL_DEBUG(SOLV_DEBUG_STATS, "file conflict detection took %d ms\n", solv_timems(start));

  return conflicts->count / 6;
}
Пример #25
0
struct solv_zchunk *
solv_zchunk_open(FILE *fp, unsigned int streamid)
{
  struct solv_zchunk *zck;
  unsigned char *p;
  unsigned int hdr_size;	/* preface + index + signatures */
  unsigned int lead_size;
  unsigned int preface_size;
  unsigned int index_size;

  zck = solv_calloc(1, sizeof(*zck));

  /* read and parse the lead, read the complete header */
  zck->hdr = solv_calloc(15, 1);
  zck->hdr_end = zck->hdr + 15;
  if (fread(zck->hdr, 15, 1, fp) != 1 || memcmp(zck->hdr, "\000ZCK1", 5) != 0)
    return open_error(zck);
  p = zck->hdr + 5;
  if ((p = getchksum(p, zck->hdr_end, &zck->hdr_chk_type, &zck->hdr_chk_len, &zck->hdr_chk_id)) == 0)
    return open_error(zck);
  if ((p = getuint(p, zck->hdr_end, &hdr_size)) == 0 || hdr_size > MAX_HDR_SIZE)
    return open_error(zck);
  lead_size = p - zck->hdr + zck->hdr_chk_len;
  zck->hdr = solv_realloc(zck->hdr, lead_size + hdr_size);
  zck->hdr_end = zck->hdr + lead_size + hdr_size;
  if (fread(zck->hdr + 15, lead_size + hdr_size - 15, 1, fp) != 1)
    return open_error(zck);

  /* verify header checksum to guard against corrupt files */
  if (zck->hdr_chk_id)
    {
      Chksum *chk = solv_chksum_create(zck->hdr_chk_id);
      if (!chk)
	return open_error(zck);
      solv_chksum_add(chk, zck->hdr, lead_size - zck->hdr_chk_len);
      solv_chksum_add(chk, zck->hdr + lead_size, hdr_size);
      if (memcmp(solv_chksum_get(chk, 0), zck->hdr + (lead_size - zck->hdr_chk_len), zck->hdr_chk_len) != 0)
	{
	  solv_chksum_free(chk, 0);
	  return open_error(zck);
	}
      solv_chksum_free(chk, 0);
    }

  /* parse preface: data chksum, flags, compression */
  p = zck->hdr + lead_size;
  if (p + zck->hdr_chk_len > zck->hdr_end)
    return open_error(zck);
  zck->data_chk_ptr = p;
  p += zck->hdr_chk_len;
#ifdef VERIFY_DATA_CHKSUM
  if (zck->hdr_chk_id && (zck->data_chk = solv_chksum_create(zck->hdr_chk_id)) == 0)
    return open_error(zck);
#endif
  if ((p = getuint(p, zck->hdr_end, &zck->flags)) == 0)
    return open_error(zck);
  if ((zck->flags & ~(3)) != 0)
    return open_error(zck);
  if ((p = getuint(p, zck->hdr_end, &zck->comp)) == 0 || (zck->comp != 0 && zck->comp != 2))
    return open_error(zck);	/* only uncompressed + zstd supported */
  /* skip all optional elements if present */
  if ((zck->flags & 2) != 0)
    {
      unsigned int nopt, lopt;
      if ((p = getuint(p, zck->hdr_end, &nopt)) == 0)
        return open_error(zck);
      for (; nopt != 0; nopt--)
	{
	  if ((p = getuint(p, zck->hdr_end, &lopt)) == 0)
            return open_error(zck);
	  if ((p = getuint(p, zck->hdr_end, &lopt)) == 0)
            return open_error(zck);
	  if (p + lopt > zck->hdr_end)
	    return open_error(zck);
	  p += lopt;
	}
    }

  preface_size = p - (zck->hdr + lead_size);

  /* parse index: index size, index chksum type, num chunks, chunk data  */
  if ((p = getuint(p, zck->hdr_end, &index_size)) == 0)
    return open_error(zck);
  if (hdr_size < preface_size + index_size)
    return open_error(zck);
  if ((p = getchksum(p, zck->hdr_end, &zck->chunk_chk_type, &zck->chunk_chk_len, &zck->chunk_chk_id)) == 0)
    return open_error(zck);
  if ((p = getuint(p, zck->hdr_end, &zck->nchunks)) == 0 || zck->nchunks > MAX_CHUNK_CNT)
    return open_error(zck);

  /* setup decompressor */
  if (zck->comp == 2)
    {
      if ((zck->dctx = ZSTD_createDCtx()) == 0)
	return open_error(zck);
    }

  zck->fp = fp;
  zck->chunks = p;
  zck->streamid = streamid;
  if (streamid == 0)
    {
      zck->nchunks = zck->nchunks ? 1 : 0;	/* limit to dict chunk */
      return zck;	
    }

  /* setup dictionary */
  if (!nextchunk(zck, 0))
    {
      zck->fp = 0;
      return open_error(zck);
    }
  if (zck->comp == 2 && zck->buf_avail)
    {
      if ((zck->ddict = ZSTD_createDDict(zck->buf, zck->buf_avail)) == 0)
	{
	  zck->fp = 0;
	  return open_error(zck);
	}
    }
  zck->buf = solv_free(zck->buf);
  zck->buf_used = 0;
  zck->buf_avail = 0;

  /* ready to read the rest of the chunks */
  return zck;
}
Пример #26
0
Id
repo_add_deb(Repo *repo, const char *deb, int flags)
{
  Pool *pool = repo->pool;
  Repodata *data;
  unsigned char buf[4096], *bp;
  int l, l2, vlen, clen, ctarlen;
  unsigned char *ctgz;
  unsigned char pkgid[16];
  unsigned char *ctar;
  int gotpkgid;
  FILE *fp;
  Solvable *s;
  struct stat stb;

  data = repo_add_repodata(repo, flags);
  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;
    }
  if (fstat(fileno(fp), &stb))
    {
      pool_error(pool, -1, "fstat: %s", strerror(errno));
      fclose(fp);
      return 0;
    }
  l = fread(buf, 1, sizeof(buf), fp);
  if (l < 8 + 60 || strncmp((char *)buf, "!<arch>\ndebian-binary   ", 8 + 16) != 0)
    {
      pool_error(pool, -1, "%s: not a deb package", deb);
      fclose(fp);
      return 0;
    }
  vlen = atoi((char *)buf + 8 + 48);
  if (vlen < 0 || vlen > l)
    {
      pool_error(pool, -1, "%s: not a deb package", deb);
      fclose(fp);
      return 0;
    }
  vlen += vlen & 1;
  if (l < 8 + 60 + vlen + 60)
    {
      pool_error(pool, -1, "%s: unhandled deb package", deb);
      fclose(fp);
      return 0;
    }
  if (strncmp((char *)buf + 8 + 60 + vlen, "control.tar.gz  ", 16) != 0)
    {
      pool_error(pool, -1, "%s: control.tar.gz is not second entry", deb);
      fclose(fp);
      return 0;
    }
  clen = atoi((char *)buf + 8 + 60 + vlen + 48);
  if (clen <= 0 || clen >= 0x100000)
    {
      pool_error(pool, -1, "%s: control.tar.gz has illegal size", deb);
      fclose(fp);
      return 0;
    }
  ctgz = solv_calloc(1, clen + 4);
  bp = buf + 8 + 60 + vlen + 60;
  l -= 8 + 60 + vlen + 60;
  if (l > clen)
    l = clen;
  if (l)
    memcpy(ctgz, bp, l);
  if (l < clen)
    {
      if (fread(ctgz + l, clen - l, 1, fp) != 1)
	{
	  pool_error(pool, -1, "%s: unexpected EOF", deb);
	  solv_free(ctgz);
	  fclose(fp);
	  return 0;
	}
    }
  fclose(fp);
  gotpkgid = 0;
  if (flags & DEBS_ADD_WITH_PKGID)
    {
      Chksum *chk = solv_chksum_create(REPOKEY_TYPE_MD5);
      solv_chksum_add(chk, ctgz, clen);
      solv_chksum_free(chk, pkgid);
      gotpkgid = 1;
    }
  if (ctgz[0] != 0x1f || ctgz[1] != 0x8b)
    {
      pool_error(pool, -1, "%s: control.tar.gz is not gzipped", deb);
      solv_free(ctgz);
      return 0;
    }
  if (ctgz[2] != 8 || (ctgz[3] & 0xe0) != 0)
    {
      pool_error(pool, -1, "%s: control.tar.gz is compressed in a strange way", deb);
      solv_free(ctgz);
      return 0;
    }
  bp = ctgz + 4;
  bp += 6;	/* skip time, xflags and OS code */
  if (ctgz[3] & 0x04)
    {
      /* skip extra field */
      l = bp[0] | bp[1] << 8;
      bp += l + 2;
      if (bp >= ctgz + clen)
	{
          pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb);
	  solv_free(ctgz);
	  return 0;
	}
    }
  if (ctgz[3] & 0x08)	/* orig filename */
    while (*bp)
      bp++;
  if (ctgz[3] & 0x10)	/* file comment */
    while (*bp)
      bp++;
  if (ctgz[3] & 0x02)	/* header crc */
    bp += 2;
  if (bp >= ctgz + clen)
    {
      pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb);
      solv_free(ctgz);
      return 0;
    }
  ctar = decompress(bp, ctgz + clen - bp, &ctarlen);
  solv_free(ctgz);
  if (!ctar)
    {
      pool_error(pool, -1, "%s: control.tar.gz is corrupt", deb);
      return 0;
    }
  bp = ctar;
  l = ctarlen;
  while (l > 512)
    {
      int j;
      l2 = 0;
      for (j = 124; j < 124 + 12; j++)
	if (bp[j] >= '0' && bp[j] <= '7')
	  l2 = l2 * 8 + (bp[j] - '0');
      if (!strcmp((char *)bp, "./control") || !strcmp((char *)bp, "control"))
	break;
      l2 = 512 + ((l2 + 511) & ~511);
      l -= l2;
      bp += l2;
    }
  if (l <= 512 || l - 512 - l2 <= 0 || l2 <= 0)
    {
      pool_error(pool, -1, "%s: control.tar.gz contains no control file", deb);
      free(ctar);
      return 0;
    }
  memmove(ctar, bp + 512, l2);
  ctar = solv_realloc(ctar, l2 + 1);
  ctar[l2] = 0;
  s = pool_id2solvable(pool, repo_add_solvable(repo));
  control2solvable(s, data, (char *)ctar);
  if (!(flags & REPO_NO_LOCATION))
    repodata_set_location(data, s - pool->solvables, 0, 0, deb);
  if (S_ISREG(stb.st_mode))
    repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size);
  if (gotpkgid)
    repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid);
  solv_free(ctar);
  if (!(flags & REPO_NO_INTERNALIZE))
    repodata_internalize(data);
  return s - pool->solvables;
}
Пример #27
0
HyPackageList
hy_packagelist_create(void)
{
    HyPackageList plist = solv_calloc(1, sizeof(*plist));
    return plist;
}
Пример #28
0
HyPackageDelta
delta_create(void) {
    HyPackageDelta delta = solv_calloc(1, sizeof(*delta));
    return delta;
}
Пример #29
0
Id
pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create)
{
  Hashval h, hh, hashmask;
  int i;
  Id id;
  Hashtable hashtbl;
  Reldep *ran;

  hashmask = pool->relhashmask;
  hashtbl = pool->relhashtbl;
  ran = pool->rels;
  
  /* extend hashtable if needed */
  if (pool->nrels * 2 > hashmask)
    {
      solv_free(pool->relhashtbl);
      pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK);
      pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id));
      /* rehash all rels into new hashtable */
      for (i = 1; i < pool->nrels; i++)
	{
	  h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask;
	  hh = HASHCHAIN_START;
	  while (hashtbl[h])
	    h = HASHCHAIN_NEXT(h, hh, hashmask);
	  hashtbl[h] = i;
	}
    }
  
  /* compute hash and check for match */
  h = relhash(name, evr, flags) & hashmask;
  hh = HASHCHAIN_START;
  while ((id = hashtbl[h]) != 0)
    {
      if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags)
	break;
      h = HASHCHAIN_NEXT(h, hh, hashmask);
    }
  if (id)
    return MAKERELDEP(id);

  if (!create)
    return ID_NULL;

  id = pool->nrels++;
  /* extend rel space if needed */
  pool->rels = solv_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK);
  hashtbl[h] = id;
  ran = pool->rels + id;
  ran->name = name;
  ran->evr = evr;
  ran->flags = flags;

  /* extend whatprovides_rel if needed */
  if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0)
    {
      pool->whatprovides_rel = solv_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset));
      memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
    }
  return MAKERELDEP(id);
}