Esempio n. 1
0
Id
pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create)
{
  Hashval h;
  unsigned int hh;
  Hashmask 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)
    {
      sat_free(pool->relhashtbl);
      pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK);
      pool->relhashtbl = hashtbl = sat_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 = sat_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 = sat_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset));
      memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset));
    }
  return MAKERELDEP(id);
}
Esempio n. 2
0
static void XMLCALL
startElement(void *userData, const char *name, const char **atts)
{
  //fprintf(stderr,"+tag: %s\n", name);
  struct parsedata *pd = userData;
  Pool *pool = pd->common.pool;
  Solvable *s = pd->solvable;
  struct stateswitch *sw;
  const char *str;
  Id handle = pd->handle;

  // fprintf(stderr, "into %s, from %d, depth %d, statedepth %d\n", name, pd->state, pd->depth, pd->statedepth);

  if (pd->depth != pd->statedepth)
    {
      pd->depth++;
      return;
    }

  if (pd->state == STATE_START && !strcmp(name, "patterns"))
    return;
  if (pd->state == STATE_START && !strcmp(name, "products"))
    return;
  //if (pd->state == STATE_START && !strcmp(name, "metadata"))
  //  return;
  if (pd->state == STATE_SOLVABLE && !strcmp(name, "format"))
    return;

  pd->depth++;
  if (!pd->swtab[pd->state])
    return;
  for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++)
    if (!strcmp(sw->ename, name))
      break;
  if (sw->from != pd->state)
    {
#if 0
      fprintf(stderr, "into unknown: %s\n", name);
#endif
      return;
    }
  pd->state = sw->to;
  pd->docontent = sw->docontent;
  pd->statedepth = pd->depth;
  pd->lcontent = 0;
  *pd->content = 0;
  switch(pd->state)
    {
    case STATE_SOLVABLE:
      pd->kind = 0;
      if (name[2] == 't' && name[3] == 't')
        pd->kind = "pattern";
      else if (name[1] == 'r')
        pd->kind = "product";
      else if (name[2] == 't' && name[3] == 'c')
        pd->kind = "patch";

      /* to support extension metadata files like others.xml which
         have the following structure:

         <otherdata xmlns="http://linux.duke.edu/metadata/other"
                    packages="101">
           <package pkgid="b78f8664cd90efe42e09a345e272997ef1b53c18"
                    name="zaptel-kmp-default"
                    arch="i586"><version epoch="0"
                    ver="1.2.10_2.6.22_rc4_git6_2" rel="70"/>
              ...

         we need to check if the pkgid is there and if it matches
         an already seen package, that means we don't need to create
         a new solvable but just append the attributes to the existing
         one.
      */
      const char *pkgid;
      if ((pkgid = find_attr("pkgid", atts)) != NULL)
        {
          // look at the checksum cache
          Id index = stringpool_str2id(&pd->cspool, pkgid, 0);
          if (!index || index >= pd->ncscache || !pd->cscache[index])
	    {
              fprintf(stderr, "error, the repository specifies extra information about package with checksum '%s', which does not exist in the repository.\n", pkgid);
              exit(1);
	    }
	  pd->solvable = pool_id2solvable(pool, pd->cscache[index]);
        }
       else
        {
          /* this is a new package */
          pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->common.repo));
          pd->freshens = 0;
        }
      pd->handle = pd->solvable - pool->solvables;
#if 0
      fprintf(stderr, "package #%d\n", pd->solvable - pool->solvables);
#endif

      break;
    case STATE_VERSION:
      s->evr = makeevr_atts(pool, pd, atts);
      break;
    case STATE_PROVIDES:
      s->provides = 0;
      break;
    case STATE_PROVIDESENTRY:
      s->provides = adddep(pool, pd, s->provides, atts, 0);
      break;
    case STATE_REQUIRES:
      s->requires = 0;
      break;
    case STATE_REQUIRESENTRY:
      s->requires = adddep(pool, pd, s->requires, atts, 1);
      break;
    case STATE_OBSOLETES:
      s->obsoletes = 0;
      break;
    case STATE_OBSOLETESENTRY:
      s->obsoletes = adddep(pool, pd, s->obsoletes, atts, 0);
      break;
    case STATE_CONFLICTS:
      s->conflicts = 0;
      break;
    case STATE_CONFLICTSENTRY:
      s->conflicts = adddep(pool, pd, s->conflicts, atts, 0);
      break;
    case STATE_RECOMMENDS:
      s->recommends = 0;
      break;
    case STATE_RECOMMENDSENTRY:
      s->recommends = adddep(pool, pd, s->recommends, atts, 0);
      break;
    case STATE_SUPPLEMENTS:
      s->supplements= 0;
      break;
    case STATE_SUPPLEMENTSENTRY:
      s->supplements = adddep(pool, pd, s->supplements, atts, 0);
      break;
    case STATE_SUGGESTS:
      s->suggests = 0;
      break;
    case STATE_SUGGESTSENTRY:
      s->suggests = adddep(pool, pd, s->suggests, atts, 0);
      break;
    case STATE_ENHANCES:
      s->enhances = 0;
      break;
    case STATE_ENHANCESENTRY:
      s->enhances = adddep(pool, pd, s->enhances, atts, 0);
      break;
    case STATE_FRESHENS:
      pd->freshens = 0;
      break;
    case STATE_FRESHENSENTRY:
      pd->freshens = adddep(pool, pd, pd->freshens, atts, 0);
      break;
    case STATE_EULA:
    case STATE_SUMMARY:
    case STATE_CATEGORY:
    case STATE_DESCRIPTION:
      pd->tmplang = find_attr("lang", atts);
      break;
    case STATE_USERVISIBLE:
      repodata_set_void(pd->data, handle, SOLVABLE_ISVISIBLE );
      break;
    case STATE_INCLUDESENTRY:
      {
	const char *tmp = find_attr("pattern", atts);
	if (tmp)
	  repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_INCLUDES, join2("pattern", ":", tmp));
      }
      break;
    case STATE_EXTENDSENTRY:
      {
	const char *tmp = find_attr("pattern", atts);
	if (tmp)
	  repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_EXTENDS, join2("pattern", ":", tmp));
      }
      break;
    case STATE_LOCATION:
      str = find_attr("href", atts);
      if (str)
	repodata_set_location(pd->data, handle, 0, 0, str);
      break;
    case STATE_CHECKSUM:
      pd->tmpattr = find_attr("type", atts);
      break;
    case STATE_TIME:
      {
        unsigned int t;
        str = find_attr("build", atts);
        if (str && (t = atoi(str)) != 0)
          repodata_set_num(pd->data, handle, SOLVABLE_BUILDTIME, t);
	break;
      }
    case STATE_SIZE:
      {
        unsigned int k;
        str = find_attr("installed", atts);
	if (str && (k = atoi(str)) != 0)
	  repodata_set_num(pd->data, handle, SOLVABLE_INSTALLSIZE, (k + 1023) / 1024);
	/* XXX the "package" attribute gives the size of the rpm file,
	   i.e. the download size.  Except on packman, there it seems to be
	   something else entirely, it has a value near to the other two
	   values, as if the rpm is uncompressed.  */
        str = find_attr("package", atts);
	if (str && (k = atoi(str)) != 0)
	  repodata_set_num(pd->data, handle, SOLVABLE_DOWNLOADSIZE, (k + 1023) / 1024);
        break;
      }
    case STATE_HEADERRANGE:
      {
        unsigned int end;
        str = find_attr("end", atts);
	if (str && (end = atoi(str)) != 0)
	  repodata_set_num(pd->data, handle, SOLVABLE_HEADEREND, end);
      }
      /*
        <diskusage>
          <dirs>
            <dir name="/" size="56" count="11"/>
            <dir name="usr/" size="56" count="11"/>
            <dir name="usr/bin/" size="38" count="10"/>
            <dir name="usr/share/" size="18" count="1"/>
            <dir name="usr/share/doc/" size="18" count="1"/>
          </dirs>
        </diskusage>
      */
    case STATE_DISKUSAGE:
      {
        /* Really, do nothing, wat for <dir> tag */
        break;
      }
    case STATE_DIR:
      {
        long filesz = 0, filenum = 0;
        unsigned dirid;
        if ((str = find_attr("name", atts)) != 0)
          dirid = repodata_str2dir(pd->data, str, 1);
        else
          {
            fprintf( stderr, "<dir .../> tag without 'name' attribute, atts = %p, *atts = %p\n",
                    (void *)atts, *atts);
            break;
          }
        if ((str = find_attr("size", atts)) != 0)
          filesz = strtol(str, 0, 0);
        if ((str = find_attr("count", atts)) != 0)
          filenum = strtol(str, 0, 0);
        pd->dirs = sat_extend(pd->dirs, pd->ndirs, 1, sizeof(pd->dirs[0]), 31);
        pd->dirs[pd->ndirs][0] = dirid;
        pd->dirs[pd->ndirs][1] = filesz;
        pd->dirs[pd->ndirs][2] = filenum;
        pd->ndirs++;
        break;
      }
    default:
      break;
    }
}
Esempio n. 3
0
void
repo_add_content(Repo *repo, FILE *fp, int flags)
{
  Pool *pool = repo->pool;
  char *line, *linep;
  int aline;
  Solvable *s;
  struct parsedata pd;
  Repodata *data;
  Id handle = 0;
  int contentstyle = 0;
  char *descrdir = 0;
  char *datadir = 0;
  char *defvendor = 0;

  int i = 0;

  /* architectures
     we use the first architecture in BASEARCHS or noarch
     for the product. At the end we create (clone) the product
     for each one of the remaining architectures
     we allow max 4 archs
  */
  unsigned int numotherarchs = 0;
  Id *otherarchs = 0;

  memset(&pd, 0, sizeof(pd));
  line = sat_malloc(1024);
  aline = 1024;

  pd.repo = repo;
  linep = line;
  s = 0;

  data = repo_add_repodata(repo, flags);

  for (;;)
    {
      char *key, *value;

      /* read line into big-enough buffer */
      if (linep - line + 16 > aline)
	{
	  aline = linep - line;
	  line = sat_realloc(line, aline + 512);
	  linep = line + aline;
	  aline += 512;
	}
      if (!fgets(linep, aline - (linep - line), fp))
	break;
      linep += strlen(linep);
      if (linep == line || linep[-1] != '\n')
        continue;
      while ( --linep > line && ( linep[-1] == ' ' ||  linep[-1] == '\t' ) )
        ; /* skip trailing ws */
      *linep = 0;
      linep = line;

      /* expect "key value" lines */
      value = line;
      key = splitword(&value);

      if (key)
        {
#if 0
	  fprintf (stderr, "key %s, value %s\n", key, value);
#endif

#define istag(x) (!strcmp (key, x))
#define code10 (contentstyle == 10)
#define code11 (contentstyle == 11)


	  if (istag ("CONTENTSTYLE"))
	    {
	      if (contentstyle)
	        pool_debug(pool, SAT_ERROR, "repo_content: 'CONTENTSTYLE' must be first line of 'content'\n");
	      contentstyle = atoi(value);
	      continue;
	    }
	  if (!contentstyle)
	    contentstyle = 10;

	  /* repository tags */
          /* we also replicate some of them into the product solvables
           * to be backward compatible */

	  if (istag ("REPOID"))
	    {
	      repodata_add_poolstr_array(data, SOLVID_META, REPOSITORY_REPOID, value);
	      continue;
	    }

	  if (istag ("DESCRDIR"))
	    {
	      if (descrdir)
		free(descrdir);
	      else
	        repo_set_str(repo, SOLVID_META, SUSETAGS_DESCRDIR, value);
	      if (s)
	        repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, value);
	      descrdir = strdup(value);
	      continue;
	    }
	  if (istag ("DATADIR"))
	    {
	      if (datadir)
		free(datadir);
	      else
	        repo_set_str(repo, SOLVID_META, SUSETAGS_DATADIR, value);
	      if (s)
	        repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, value);
	      datadir = strdup(value);
	      continue;
	    }
	  if (istag ("VENDOR"))
	    {
	      if (defvendor)
		free(defvendor);
	      else
	        repo_set_poolstr(repo, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value);
	      if (s)
		s->vendor = str2id(pool, value, 1);
	      defvendor = strdup(value);
	      continue;
	    }

	  if (istag ("META") || istag ("HASH") || istag ("KEY"))
	    {
	      char *checksumtype, *checksum;
	      Id fh, type;
	      int l;

	      if ((checksumtype = splitword(&value)) == 0)
		continue;
	      if ((checksum = splitword(&value)) == 0)
		continue;
	      if (!*value)
		continue;
	      if (!strcasecmp(checksumtype, "sha") || !strcasecmp(checksumtype, "sha1"))
	        l = SIZEOF_SHA1 * 2, type = REPOKEY_TYPE_SHA1;
	      else if (!strcasecmp(checksumtype, "sha256"))
	        l = SIZEOF_SHA256 * 2, type = REPOKEY_TYPE_SHA256;
	      else if (!strcasecmp(checksumtype, "md5"))
	        l = SIZEOF_MD5 * 2, type = REPOKEY_TYPE_MD5;
	      else
	        {
		  fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype);
		  exit(1);
	        }
	      if (strlen(checksum) != l)
	        {
		  fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum);
		  exit(1);
	        }
	      fh = repodata_new_handle(data);
	      repodata_set_poolstr(data, fh, SUSETAGS_FILE_TYPE, key);
	      repodata_set_str(data, fh, SUSETAGS_FILE_NAME, value);
	      repodata_set_checksum(data, fh, SUSETAGS_FILE_CHECKSUM, type, checksum);
	      repodata_add_flexarray(data, SOLVID_META, SUSETAGS_FILE, fh);
	      continue;
	    }

	  /* product tags */

	  if ((code10 && istag ("PRODUCT"))
	      || (code11 && istag ("NAME")))
	    {
	      if (s && !s->name)
		{
		  /* this solvable was created without seeing a
		     PRODUCT entry, just set the name and continue */
		  s->name = str2id(pool, join(&pd, "product", ":", value), 1);
		  continue;
		}
	      if (s)
		{
		  /* finish old solvable */
		  if (!s->arch)
		    s->arch = ARCH_NOARCH;
		  if (!s->evr)
		    s->evr = ID_EMPTY;
		  if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
		    s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
		  if (code10)
		    s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);
		}
	      /* create new solvable */
	      s = pool_id2solvable(pool, repo_add_solvable(repo));
	      repodata_extend(data, s - pool->solvables);
	      handle = s - pool->solvables;
	      s->name = str2id(pool, join(&pd, "product", ":", value), 1);
	      if (datadir)
	        repo_set_str(repo, s - pool->solvables, SUSETAGS_DATADIR, datadir);
	      if (descrdir)
	        repo_set_str(repo, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir);
	      if (defvendor)
		s->vendor = str2id(pool, defvendor, 1);
	      continue;
	    }

	  /* Sometimes PRODUCT/NAME is not the first entry, but we need a solvable
	     from here on.  */
	  if (!s)
	    {
	      s = pool_id2solvable(pool, repo_add_solvable(repo));
	      repodata_extend(data, s - pool->solvables);
	      handle = s - pool->solvables;
	    }

	  if (istag ("VERSION"))
            pd.tmpvers = strdup(value);
          else if (istag ("RELEASE"))
            pd.tmprel = strdup(value);
	  else if (code11 && istag ("DISTRIBUTION"))
	    repo_set_str(repo, s - pool->solvables, SOLVABLE_DISTRIBUTION, value);
	  else if (istag ("UPDATEURLS"))
	    add_multiple_urls(data, handle, value, str2id(pool, "update", 1));
	  else if (istag ("EXTRAURLS"))
	    add_multiple_urls(data, handle, value, str2id(pool, "extra", 1));
	  else if (istag ("OPTIONALURLS"))
	    add_multiple_urls(data, handle, value, str2id(pool, "optional", 1));
	  else if (istag ("RELNOTESURL"))
	    add_multiple_urls(data, handle, value, str2id(pool, "releasenotes", 1));
	  else if (istag ("SHORTLABEL"))
	    repo_set_str(repo, s - pool->solvables, PRODUCT_SHORTLABEL, value);
	  else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */
	    repo_set_str(repo, s - pool->solvables, SOLVABLE_SUMMARY, value);
	  else if (!strncmp (key, "LABEL.", 6))
	    repo_set_str(repo, s - pool->solvables, pool_id2langid(pool, SOLVABLE_SUMMARY, key + 6, 1), value);
	  else if (istag ("FLAGS"))
	    add_multiple_strings(data, handle, PRODUCT_FLAGS, value);
	  else if (istag ("VENDOR"))	/* actually already handled above */
	    s->vendor = str2id(pool, value, 1);
          else if (istag ("BASEARCHS"))
            {
              char *arch;

	      if ((arch = splitword(&value)) != 0)
		{
		  s->arch = str2id(pool, arch, 1);
		  while ((arch = splitword(&value)) != 0)
		    {
		       otherarchs = sat_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7);
		       otherarchs[numotherarchs++] = str2id(pool, arch, 1);
		    }
		}
            }

	  /*
	   * Every tag below is Code10 only
	   *
	   */

	  if (code10 && istag ("DISTPRODUCT"))
	    /* DISTPRODUCT is for registration and Yast, not for the solver. */
	    repo_set_str(repo, s - pool->solvables, PRODUCT_DISTPRODUCT, value);
	  else if (code10 && istag ("DISTVERSION"))
	    /* DISTVERSION is for registration and Yast, not for the solver. */
	    repo_set_str(repo, s - pool->solvables, PRODUCT_DISTVERSION, value);
	  else if (code10 && istag ("ARCH"))
	    /* Theoretically we want to have the best arch of the given
	       modifiers which still is compatible with the system
	       arch.  We don't know the latter here, though.  */
	    s->arch = ARCH_NOARCH;
	  else if (code10 && istag ("PREREQUIRES"))
	    s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER);
	  else if (code10 && istag ("REQUIRES"))
	    s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER);
	  else if (code10 && istag ("PROVIDES"))
	    s->provides = adddep(pool, &pd, s->provides, value, 0);
	  else if (code10 && istag ("CONFLICTS"))
	    s->conflicts = adddep(pool, &pd, s->conflicts, value, 0);
	  else if (code10 && istag ("OBSOLETES"))
	    s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0);
	  else if (code10 && istag ("RECOMMENDS"))
	    s->recommends = adddep(pool, &pd, s->recommends, value, 0);
	  else if (code10 && istag ("SUGGESTS"))
	    s->suggests = adddep(pool, &pd, s->suggests, value, 0);
	  else if (code10 && istag ("SUPPLEMENTS"))
	    s->supplements = adddep(pool, &pd, s->supplements, value, 0);
	  else if (code10 && istag ("ENHANCES"))
	    s->enhances = adddep(pool, &pd, s->enhances, value, 0);
	  /* FRESHENS doesn't seem to exist.  */
	  else if (code10 && istag ("TYPE"))
	    repo_set_str(repo, s - pool->solvables, PRODUCT_TYPE, value);

	  /* XXX do something about LINGUAS and ARCH?
          * <ma>: Don't think so. zypp does not use or propagate them.
          */
#undef istag
	}
      else
	pool_debug(pool, SAT_ERROR, "repo_content: malformed line: %s\n", line);
    }

  if (datadir)
    free(datadir);
  if (descrdir)
    free(descrdir);
  if (defvendor)
    free(defvendor);

  if (s)
    {
      if (!s->name)
	{
	  pool_debug(pool, SAT_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n");
	  exit(1);
	}

      if (pd.tmprel)
	s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel));
      else
	s->evr = makeevr(pool, pd.tmpvers);
      pd.tmpvers = sat_free((void *)pd.tmpvers);
      pd.tmprel = sat_free((void *)pd.tmprel);

      if (!s->arch)
	s->arch = ARCH_NOARCH;
      if (!s->evr)
	s->evr = ID_EMPTY;
      if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC)
        s->provides = repo_addid_dep(repo, s->provides, rel2id(pool, s->name, s->evr, REL_EQ, 1), 0);
      if (code10)
	s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, 0);

      /* now for every other arch, clone the product except the architecture */
      for (i = 0; i < numotherarchs; ++i)
	{
	  Solvable *p = pool_id2solvable(pool, repo_add_solvable(repo));
	  repodata_extend(data, p - pool->solvables);
	  p->name = s->name;
	  p->evr = s->evr;
	  p->vendor = s->vendor;
	  p->arch = otherarchs[i];

	  /* self provides */
	  if (s->name && p->arch != ARCH_SRC && p->arch != ARCH_NOSRC)
	      p->provides = repo_addid_dep(repo, p->provides, rel2id(pool, p->name, p->evr, REL_EQ, 1), 0);

	  /* now merge the attributes */
	  repodata_merge_attrs(data, p - pool->solvables, s - pool->solvables);
	}
    }

  if (pd.tmp)
    sat_free(pd.tmp);
  sat_free(line);
  sat_free(otherarchs);
  join_freemem();
  if (!(flags & REPO_NO_INTERNALIZE))
    repodata_internalize(data);
}