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; } }
int repo_add_cudf(Repo *repo, Repo *installedrepo, FILE *fp, Queue *job, int flags) { Pool *pool = repo->pool; char *buf, *p; int bufa, bufl, c; Solvable *s; int instanza = 0; int inrequest = 0; int isinstalled = 0; int keep = 0; Repo *xrepo; xrepo = repo ? repo : installedrepo; if (!xrepo) return -1; buf = solv_malloc(4096); bufa = 4096; bufl = 0; s = 0; while (fgets(buf + bufl, bufa - bufl, fp) > 0) { bufl += strlen(buf + bufl); if (bufl && buf[bufl - 1] != '\n') { if (bufa - bufl < 256) { bufa += 4096; buf = solv_realloc(buf, bufa); } continue; } buf[--bufl] = 0; c = getc(fp); if (c == ' ' || c == '\t') { /* continuation line */ buf[bufl++] = ' '; continue; } if (c != EOF) ungetc(c, fp); bufl = 0; if (*buf == '#') continue; if (!*buf) { if (s && !repo && !isinstalled) { repo_free_solvable(repo, s - pool->solvables, 1); s = 0; } if (s) finishpackage(pool, s, keep, job); s = 0; keep = 0; instanza = 0; inrequest = 0; continue; } p = strchr(buf, ':'); if (!p) continue; /* hmm */ *p++ = 0; while (*p == ' ' || *p == '\t') p++; if (!instanza) { instanza = 1; inrequest = 0; if (!strcmp(buf, "request")) { inrequest = 1; continue; } if (!strcmp(buf, "package")) { s = pool_id2solvable(pool, repo_add_solvable(xrepo)); isinstalled = 0; keep = 0; } } if (inrequest) { if (!job) continue; if (!strcmp(buf, "install")) { Id id, *idp; Offset off = makedeps(xrepo, p, 0, 0); for (idp = xrepo->idarraydata + off; (id = *idp) != 0; idp++) queue_push2(job, SOLVER_INSTALL|SOLVER_SOLVABLE_PROVIDES, id); } else if (!strcmp(buf, "remove")) { Id id, *idp; Offset off = makedeps(xrepo, p, 0, 0); for (idp = xrepo->idarraydata + off; (id = *idp) != 0; idp++) queue_push2(job, SOLVER_ERASE|SOLVER_SOLVABLE_PROVIDES, id); } else if (!strcmp(buf, "upgrade")) { Id id, *idp; Offset off = makedeps(xrepo, p, 0, 0); for (idp = xrepo->idarraydata + off; (id = *idp) != 0; idp++) queue_push2(job, SOLVER_INSTALL|SOLVER_ORUPDATE|SOLVER_SOLVABLE_PROVIDES, id); } continue; } if (!s) continue; /* we ignore the preamble for now */ switch (buf[0]) { case 'c': if (!strcmp(buf, "conflicts")) { s->conflicts = makedeps(s->repo, p, s->conflicts, 0); continue; } case 'd': if (!strcmp(buf, "depends")) { s->requires = makedeps(s->repo, p, s->requires, 0); continue; } break; case 'k': if (!strcmp(buf, "keep")) { if (!job) continue; if (!strcmp(p, "version")) keep = KEEP_VERSION; else if (!strcmp(p, "package")) keep = KEEP_PACKAGE; else if (!strcmp(p, "feature")) keep = KEEP_FEATURE; continue; } break; case 'i': if (!strcmp(buf, "installed")) { if (!strcmp(p, "true")) { isinstalled = 1; if (!installedrepo) { repo_free_solvable(repo, s - pool->solvables, 1); s = 0; } else if (s->repo != installedrepo) { copysolvabledata(pool, s, installedrepo); s->repo->nsolvables--; s->repo = installedrepo; if (s - pool->solvables < s->repo->start) s->repo->start = s - pool->solvables; if (s - pool->solvables >= s->repo->end) s->repo->end = s - pool->solvables + 1; s->repo->nsolvables++; } } continue; } break; case 'p': if (!strcmp(buf, "package")) { s->name = pool_str2id(pool, p, 1); continue; } if (!strcmp(buf, "provides")) { s->provides = makedeps(s->repo, p, s->provides, 0); continue; } break; case 'r': if (!strcmp(buf, "depends")) { s->recommends = makedeps(s->repo, p, s->recommends, 0); continue; } break; case 'v': if (!strcmp(buf, "version")) { s->evr = pool_str2id(pool, p, 1); continue; } break; } } if (s && !repo && !isinstalled) { repo_free_solvable(repo, s - pool->solvables, 1); s = 0; } if (s) finishpackage(pool, s, keep, job); solv_free(buf); return 0; }
/* internal */ static Solvable * get_solvable(HifPackage *pkg) { HifPackagePrivate *priv = GET_PRIVATE(pkg); return pool_id2solvable(hif_package_get_pool(pkg), priv->id); }
int repo_add_debpackages(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; Repodata *data; char *buf, *p; int bufl, l, ll; Solvable *s; data = repo_add_repodata(repo, flags); buf = solv_malloc(4096); bufl = 4096; l = 0; buf[l] = 0; p = buf; for (;;) { if (!(p = strchr(p, '\n'))) { int l3; if (l + 1024 >= bufl) { buf = solv_realloc(buf, bufl + 4096); bufl += 4096; p = buf + l; continue; } p = buf + l; ll = fread(p, 1, bufl - l - 1, fp); if (ll <= 0) break; p[ll] = 0; while ((l3 = strlen(p)) < ll) p[l3] = '\n'; l += ll; continue; } p++; if (*p != '\n') continue; *p = 0; ll = p - buf + 1; s = pool_id2solvable(pool, repo_add_solvable(repo)); control2solvable(s, data, buf); if (!s->name) repo_free_solvable(repo, s - pool->solvables, 1); if (l > ll) memmove(buf, p + 1, l - ll); l -= ll; p = buf; buf[l] = 0; } if (l) { s = pool_id2solvable(pool, repo_add_solvable(repo)); control2solvable(s, data, buf); if (!s->name) repo_free_solvable(repo, s - pool->solvables, 1); } solv_free(buf); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 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; }
int repo_add_autopattern(Repo *repo, int flags) { Pool *pool = repo->pool; Repodata *data = 0; Solvable *s, *s2; Queue patq, patq2; Queue prdq, prdq2; Id p; Id pattern_id, product_id; Id autopattern_id = 0, autoproduct_id = 0; int i, j; queue_init(&patq); queue_init(&patq2); queue_init(&prdq); queue_init(&prdq2); pattern_id = pool_str2id(pool, "pattern()", 9); product_id = pool_str2id(pool, "product()", 9); FOR_REPO_SOLVABLES(repo, p, s) { const char *n = pool_id2str(pool, s->name); if (*n == 'p') { if (!strncmp("pattern:", n, 8)) { queue_push(&patq, p); continue; } else if (!strncmp("product:", n, 8)) { queue_push(&prdq, p); continue; } } if (s->provides) { Id prv, *prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; if (rd->name == pattern_id) { queue_push2(&patq2, p, rd->evr); break; } if (rd->name == product_id) { queue_push2(&prdq2, p, rd->evr); break; } } } } for (i = 0; i < patq2.count; i += 2) { const char *pn = 0; char *newname; Id name, prv, *prvp; const char *str; unsigned long long num; s = pool->solvables + patq2.elements[i]; /* construct new name */ newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, patq2.elements[i + 1]), 0); unescape(newname); name = pool_str2id(pool, newname, 0); if (name) { /* check if we already have that pattern */ for (j = 0; j < patq.count; j++) { s2 = pool->solvables + patq.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr) break; } if (j < patq.count) continue; /* yes, do not add again */ } /* new pattern */ if (!name) name = pool_str2id(pool, newname, 1); if (!data) { repo_internalize(repo); /* to make that the lookups work */ data = repo_add_repodata(repo, flags); } s2 = pool_id2solvable(pool, repo_add_solvable(repo)); s = pool->solvables + patq2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = s->evr; s2->vendor = s->vendor; /* add link requires */ s2->requires = repo_addid_dep(repo, s2->requires, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1) , 0); /* add autopattern provides */ if (!autopattern_id) autopattern_id = pool_str2id(pool, "autopattern()", 1); s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autopattern_id, s->name, REL_EQ, 1), 0); /* add self provides */ s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0); if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_INSTALLTIME, num); if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num); if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str); if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str); /* fill in stuff from provides */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { Id evr = 0; if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; prv = rd->name; evr = rd->evr; } pn = pool_id2str(pool, prv); if (strncmp("pattern-", pn, 8) != 0) continue; newname = 0; if (evr) { newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0); unescape(newname); } if (!strncmp(pn, "pattern-category(", 17) && evr) { char lang[9]; int l = strlen(pn); Id langtag; if (l > 17 + 9 || pn[l - 1] != ')') continue; strncpy(lang, pn + 17, l - 17 - 1); lang[l - 17 - 1] = 0; langtag = SOLVABLE_CATEGORY; if (*lang && strcmp(lang, "en") != 0) langtag = pool_id2langid(pool, SOLVABLE_CATEGORY, lang, 1); if (newname[solv_validutf8(newname)] == 0) repodata_set_str(data, s2 - pool->solvables, langtag, newname); else { char *ustr = solv_latin1toutf8(newname); repodata_set_str(data, s2 - pool->solvables, langtag, ustr); solv_free(ustr); } } else if (!strcmp(pn, "pattern-includes()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_INCLUDES, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-extends()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_EXTENDS, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-icon()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ICON, newname); else if (!strcmp(pn, "pattern-order()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ORDER, newname); else if (!strcmp(pn, "pattern-visible()") && !evr) repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE); } } queue_free(&patq); queue_free(&patq2); if (repo == pool->installed) queue_empty(&prdq2); /* no auto products for installed repos */ for (i = 0; i < prdq2.count; i += 2) { const char *pn = 0; char *newname; Id name, evr = 0, prv, *prvp; const char *str; unsigned long long num; s = pool->solvables + prdq2.elements[i]; /* construct new name */ newname = pool_tmpjoin(pool, "product(", pool_id2str(pool, prdq2.elements[i + 1]), ")"); unescape(newname); name = pool_str2id(pool, newname, 0); if (!name) continue; /* must have it in provides! */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->name == name && rd->flags == REL_EQ) { evr = rd->evr; break; } } } if (!prv) continue; /* not found in provides */ newname = pool_tmpjoin(pool, "product:", pool_id2str(pool, prdq2.elements[i + 1]), 0); unescape(newname); name = pool_str2id(pool, newname, 0); if (name) { /* check if we already have that product */ for (j = 0; j < prdq.count; j++) { s2 = pool->solvables + prdq.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == evr) break; } if (j < prdq.count) continue; /* yes, do not add again */ } /* new product */ if (!name) name = pool_str2id(pool, newname, 1); if (!data) { repo_internalize(repo); /* to make that the lookups work */ data = repo_add_repodata(repo, flags); } if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0) continue; /* eek, not for installed packages, please! */ s2 = pool_id2solvable(pool, repo_add_solvable(repo)); s = pool->solvables + prdq2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = evr; s2->vendor = s->vendor; /* add link requires */ s2->requires = repo_addid_dep(repo, s2->requires, prv, 0); if (!autoproduct_id) autoproduct_id = pool_str2id(pool, "autoproduct()", 1); s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autoproduct_id, s->name, REL_EQ, 1), 0); /* add self provides */ s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0); if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num); if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str); if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str); if ((str = solvable_lookup_str(s, SOLVABLE_DISTRIBUTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DISTRIBUTION, str); /* fill in stuff from provides */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { Id evr = 0; if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; prv = rd->name; evr = rd->evr; } pn = pool_id2str(pool, prv); if (strncmp("product-", pn, 8) != 0) continue; newname = 0; if (evr) { newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0); unescape(newname); } if (!strcmp(pn, "product-label()") && evr) repodata_set_str(data, s2 - pool->solvables, PRODUCT_SHORTLABEL, newname); else if (!strcmp(pn, "product-type()") && evr) repodata_set_str(data, s2 - pool->solvables, PRODUCT_TYPE, newname); else if (!strcmp(pn, "product-cpeid()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_CPEID, newname); else if (!strcmp(pn, "product-flags()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_FLAGS, newname); else if (!strcmp(pn, "product-updates-repoid()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_UPDATES_REPOID, newname); else if (!strncmp(pn, "product-url(", 12) && evr && pn[12] && pn[13] && strlen(pn + 12) < 32) { char type[34]; strcpy(type, pn + 12); type[strlen(type) - 1] = 0; /* closing ) */ repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_URL_TYPE, type); repodata_add_poolstr_array(data, s2 - pool->solvables, PRODUCT_URL, newname); } } } queue_free(&prdq); queue_free(&prdq2); if (data && !(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); else if (!data && !(flags & REPO_NO_INTERNALIZE)) repo_internalize(repo); return 0; }
int repo_add_autopattern(Repo *repo, int flags) { Pool *pool = repo->pool; Repodata *data = 0; Solvable *s, *s2; Queue q, q2; Id p; Id pattern_id; Id autopattern_id = 0; int i, j; queue_init(&q); queue_init(&q2); pattern_id = pool_str2id(pool, "pattern()", 9); FOR_REPO_SOLVABLES(repo, p, s) { const char *n = pool_id2str(pool, s->name); if (!strncmp("pattern:", n, 8)) queue_push(&q, p); else if (s->provides) { Id prv, *prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->name == pattern_id && rd->flags == REL_EQ) { queue_push2(&q2, p, rd->evr); break; } } } } for (i = 0; i < q2.count; i += 2) { const char *pn = 0; char *newname; Id name, prv, *prvp; const char *str; unsigned long long num; s = pool->solvables + q2.elements[i]; /* construct new name */ newname = pool_tmpjoin(pool, "pattern:", pool_id2str(pool, q2.elements[i + 1]), 0); unescape(newname); name = pool_str2id(pool, newname, 0); if (name) { /* check if we already have that pattern */ for (j = 0; j < q.count; j++) { s2 = pool->solvables + q.elements[j]; if (s2->name == name && s2->arch == s->arch && s2->evr == s->evr) break; } if (j < q.count) continue; /* yes, do not add again */ } /* new pattern */ if (!name) name = pool_str2id(pool, newname, 1); if (!data) { repo_internalize(repo); /* to make that the lookups work */ data = repo_add_repodata(repo, flags); } s2 = pool_id2solvable(pool, repo_add_solvable(repo)); s = pool->solvables + q2.elements[i]; /* re-calc pointer */ s2->name = name; s2->arch = s->arch; s2->evr = s->evr; s2->vendor = s->vendor; /* add link requires */ s2->requires = repo_addid_dep(repo, s2->requires, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1) , 0); /* add autopattern provides */ if (!autopattern_id) autopattern_id = pool_str2id(pool, "autopattern()", 1); s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, autopattern_id, s->name, REL_EQ, 1), 0); /* add self provides */ s2->provides = repo_addid_dep(repo, s2->provides, pool_rel2id(pool, s2->name, s2->evr, REL_EQ, 1), 0); if ((num = solvable_lookup_num(s, SOLVABLE_INSTALLTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_INSTALLTIME, num); if ((num = solvable_lookup_num(s, SOLVABLE_BUILDTIME, 0)) != 0) repodata_set_num(data, s2 - pool->solvables, SOLVABLE_BUILDTIME, num); if ((str = solvable_lookup_str(s, SOLVABLE_SUMMARY)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_SUMMARY, str); if ((str = solvable_lookup_str(s, SOLVABLE_DESCRIPTION)) != 0) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_DESCRIPTION, str); /* fill in stuff from provides */ prvp = repo->idarraydata + s->provides; while ((prv = *prvp++) != 0) /* go through all provides */ { Id evr = 0; if (ISRELDEP(prv)) { Reldep *rd = GETRELDEP(pool, prv); if (rd->flags != REL_EQ) continue; prv = rd->name; evr = rd->evr; } pn = pool_id2str(pool, prv); if (strncmp("pattern-", pn, 8) != 0) continue; newname = 0; if (evr) { newname = pool_tmpjoin(pool, pool_id2str(pool, evr), 0, 0); unescape(newname); } if (!strncmp(pn, "pattern-category(", 17) && evr) { char lang[9]; int l = strlen(pn); Id langtag; if (l > 17 + 9 || pn[l - 1] != ')') continue; strncpy(lang, pn + 17, l - 17 - 1); lang[l - 17 - 1] = 0; langtag = SOLVABLE_CATEGORY; if (*lang && strcmp(lang, "en") != 0) langtag = pool_id2langid(pool, SOLVABLE_CATEGORY, lang, 1); repodata_set_str(data, s2 - pool->solvables, langtag, newname); } else if (!strcmp(pn, "pattern-includes()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_INCLUDES, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-extends()") && evr) repodata_add_poolstr_array(data, s2 - pool->solvables, SOLVABLE_EXTENDS, pool_tmpjoin(pool, "pattern:", newname, 0)); else if (!strcmp(pn, "pattern-icon()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ICON, newname); else if (!strcmp(pn, "pattern-order()") && evr) repodata_set_str(data, s2 - pool->solvables, SOLVABLE_ORDER, newname); else if (!strcmp(pn, "pattern-visible()") && !evr) repodata_set_void(data, s2 - pool->solvables, SOLVABLE_ISVISIBLE); } } queue_free(&q); queue_free(&q2); if (data && !(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); else if (!data && !(flags & REPO_NO_INTERNALIZE)) repo_internalize(repo); return 0; }
int 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 = solv_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 = solv_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, SOLV_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 repodata_set_str(data, SOLVID_META, SUSETAGS_DESCRDIR, value); if (s) repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, value); descrdir = solv_strdup(value); continue; } if (istag ("DATADIR")) { if (datadir) free(datadir); else repodata_set_str(data, SOLVID_META, SUSETAGS_DATADIR, value); if (s) repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, value); datadir = solv_strdup(value); continue; } if (istag ("VENDOR")) { if (defvendor) free(defvendor); else repodata_set_poolstr(data, SOLVID_META, SUSETAGS_DEFAULTVENDOR, value); if (s) s->vendor = pool_str2id(pool, value, 1); defvendor = solv_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; type = solv_chksum_str2type(checksumtype); if (!type) { fprintf(stderr, "Unknown checksum type: %s: %s\n", value, checksumtype); continue; } l = solv_chksum_len(type); if (strlen(checksum) != 2 * l) { fprintf(stderr, "Invalid checksum length: %s: for %s\n", value, checksum); continue; } 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 = pool_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, pool_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 = pool_str2id(pool, join(&pd, "product", ":", value), 1); if (datadir) repodata_set_str(data, s - pool->solvables, SUSETAGS_DATADIR, datadir); if (descrdir) repodata_set_str(data, s - pool->solvables, SUSETAGS_DESCRDIR, descrdir); if (defvendor) s->vendor = pool_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 = solv_strdup(value); else if (istag ("RELEASE")) pd.tmprel = solv_strdup(value); else if (code11 && istag ("DISTRIBUTION")) repodata_set_str(data, s - pool->solvables, SOLVABLE_DISTRIBUTION, value); else if (istag ("UPDATEURLS")) add_multiple_urls(data, handle, value, pool_str2id(pool, "update", 1)); else if (istag ("EXTRAURLS")) add_multiple_urls(data, handle, value, pool_str2id(pool, "extra", 1)); else if (istag ("OPTIONALURLS")) add_multiple_urls(data, handle, value, pool_str2id(pool, "optional", 1)); else if (istag ("RELNOTESURL")) add_multiple_urls(data, handle, value, pool_str2id(pool, "releasenotes", 1)); else if (istag ("SHORTLABEL")) repodata_set_str(data, s - pool->solvables, PRODUCT_SHORTLABEL, value); else if (istag ("LABEL")) /* LABEL is the products SUMMARY. */ repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, value); else if (!strncmp (key, "LABEL.", 6)) repodata_set_str(data, 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 = pool_str2id(pool, value, 1); else if (istag ("BASEARCHS")) { char *arch; if ((arch = splitword(&value)) != 0) { s->arch = pool_str2id(pool, arch, 1); while ((arch = splitword(&value)) != 0) { otherarchs = solv_extend(otherarchs, numotherarchs, 1, sizeof(Id), 7); otherarchs[numotherarchs++] = pool_str2id(pool, arch, 1); } } } /* * Every tag below is Code10 only * */ if (code10 && istag ("DISTPRODUCT")) /* DISTPRODUCT is for registration and Yast, not for the solver. */ repodata_set_str(data, s - pool->solvables, PRODUCT_DISTPRODUCT, value); else if (code10 && istag ("DISTVERSION")) /* DISTVERSION is for registration and Yast, not for the solver. */ repodata_set_str(data, 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")) repodata_set_str(data, 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, SOLV_ERROR, "repo_content: malformed line: %s\n", line); } if (datadir) free(datadir); if (descrdir) free(descrdir); if (defvendor) free(defvendor); if (s && !s->name) { pool_debug(pool, SOLV_FATAL, "repo_content: 'content' incomplete, no product solvable created!\n"); repo_free_solvable_block(repo, s - pool->solvables, 1, 1); s = 0; } if (s) { if (pd.tmprel) s->evr = makeevr(pool, join(&pd, pd.tmpvers, "-", pd.tmprel)); else s->evr = makeevr(pool, pd.tmpvers); pd.tmpvers = solv_free((void *)pd.tmpvers); pd.tmprel = solv_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, pool_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, pool_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) solv_free(pd.tmp); solv_free(line); solv_free(otherarchs); join_freemem(); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; }
static void add_releasefile_product(Repo *repo, FILE *fp) { Pool *pool = repo->pool; char buf[BUFF_SIZE]; Id name = 0; Id arch = 0; Id version = 0; int lnum = 0; /* line number */ char *ptr, *ptr1; /* parse /etc/<xyz>-release file */ while (fgets(buf, sizeof(buf), fp)) { /* remove trailing \n */ int l = strlen(buf); if (l && buf[l - 1] == '\n') buf[--l] = 0; ++lnum; if (lnum == 1) { /* 1st line, <name> [(<arch>)] */ ptr = strchr(buf, '('); if (ptr) { ptr1 = ptr - 1; *ptr++ = 0; } else ptr1 = buf + l - 1; /* track back until non-blank, non-digit */ while (ptr1 > buf && (*ptr1 == ' ' || isdigit(*ptr1) || *ptr1 == '.')) --ptr1; *(++ptr1) = 0; name = pool_str2id(pool, join2("product", ":", buf), 1); if (ptr) { /* have arch */ char *ptr1 = strchr(ptr, ')'); if (ptr1) { *ptr1 = 0; /* downcase arch */ ptr1 = ptr; while (*ptr1) { if (isupper(*ptr1)) *ptr1 = tolower(*ptr1); ++ptr1; } arch = pool_str2id(pool, ptr, 1); } } } else if (strncmp(buf, "VERSION", 7) == 0) { ptr = strchr(buf + 7, '='); if (ptr) { while (*++ptr == ' ') ; version = makeevr(pool, ptr); } } } if (name) { Solvable *s = pool_id2solvable(pool, repo_add_solvable(repo)); s->name = name; s->evr = version ? version : ID_EMPTY; s->arch = arch ? arch : ARCH_NOARCH; if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); } }
Id ModulePackage::createPlatformSolvable(DnfSack * sack, DnfSack * moduleSack, const std::vector<std::string> & osReleasePaths, const std::string install_root, const char * platformModule) { std::pair<std::string, std::string> parsedPlatform; std::string name; std::string stream; if (platformModule) { parsedPlatform = parsePlatform(platformModule); if (!parsedPlatform.first.empty() && !parsedPlatform.second.empty()) { name = parsedPlatform.first; stream = parsedPlatform.second; } else { throw std::runtime_error( tfm::format(_("Invalid format of Platform module: %s"), platformModule)); } } else if (sack) { Query baseQuery(sack); baseQuery.addFilter(HY_PKG_PROVIDES, HY_EQ, "system-release"); baseQuery.addFilter(HY_PKG_LATEST, HY_EQ, 1); baseQuery.apply(); Query availableQuery(baseQuery); availableQuery.addFilter(HY_PKG_REPONAME, HY_NEQ, HY_SYSTEM_REPO_NAME); auto platform = availableQuery.getStringsFromProvide("base-module"); auto platformSize = platform.size(); if (platformSize == 1) { parsedPlatform = parsePlatform(*platform.begin()); } else if (platformSize > 1) { auto logger(Log::getLogger()); logger->debug(_("Multiple module platforms provided by available packages\n")); } if (!parsedPlatform.first.empty() && !parsedPlatform.second.empty()) { name = parsedPlatform.first; stream = parsedPlatform.second; } else { baseQuery.addFilter(HY_PKG_REPONAME, HY_EQ, HY_SYSTEM_REPO_NAME); platform = baseQuery.getStringsFromProvide("base-module"); platformSize = platform.size(); if (platformSize == 1) { parsedPlatform = parsePlatform(*platform.begin()); } else if (platformSize > 1) { auto logger(Log::getLogger()); logger->debug(_("Multiple module platforms provided by installed packages\n")); } if (!parsedPlatform.first.empty() && !parsedPlatform.second.empty()) { name = parsedPlatform.first; stream = parsedPlatform.second; } } } if (name.empty() || stream.empty()) { for (auto & osReleasePath: osReleasePaths) { std::string path; if (install_root == "/") { path = osReleasePath; } else { if (install_root.back() == '/') { path = install_root.substr(0, install_root.size() -1); } else { path = install_root; } path += osReleasePath; } std::pair<std::string, std::string> platform; try { platform = getPlatformStream(path); } catch (const std::exception & except) { auto logger(Log::getLogger()); logger->debug(tfm::format(_("Detection of Platform Module in %s failed: %s"), osReleasePath, std::string(except.what()))); } if (!platform.first.empty() && !platform.second.empty()) { name = platform.first; stream = platform.second; break; } else { auto logger(Log::getLogger()); logger->debug(tfm::format(_("Missing PLATFORM_ID in %s"), osReleasePath)); } } } if (name.empty() || stream.empty()) { throw std::runtime_error(_("No valid Platform ID detected")); } std::string version = "0"; std::string context = "00000000"; Pool * pool = dnf_sack_get_pool(moduleSack); HyRepo hrepo = hy_repo_create(HY_SYSTEM_REPO_NAME); auto repoImpl = libdnf::repoGetImpl(hrepo); LibsolvRepo *repo = repo_create(pool, HY_SYSTEM_REPO_NAME); repo->appdata = hrepo; repoImpl->libsolvRepo = repo; repoImpl->needs_internalizing = 1; Id id = repo_add_solvable(repo); Solvable *solvable = pool_id2solvable(pool, id); setSovable(pool, solvable, name, stream, version, context, "noarch"); repoImpl->needs_internalizing = 1; dnf_sack_set_provides_not_ready(moduleSack); dnf_sack_set_considered_to_update(moduleSack); pool_set_installed(pool, repo); return id; }
static void XMLCALL startElement(void *userData, const char *name, const char **atts) { Parsedata *pd = (Parsedata *)userData; struct stateswitch *sw; Pool *pool = pd->pool; Solvable *s = pd->solvable; if (pd->depth != pd->statedepth) { pd->depth++; return; } /* ignore deps element */ if (pd->state == STATE_PACKAGE && !strcmp(name, "deps")) return; pd->depth++; /* find node name in stateswitch */ if (!pd->swtab[pd->state]) return; for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) { if (!strcmp(sw->ename, name)) break; } /* check if we're at the right level */ if (sw->from != pd->state) { #if 0 fprintf(stderr, "into unknown: %s\n", name); #endif return; } /* set new state */ pd->state = sw->to; pd->docontent = sw->docontent; pd->statedepth = pd->depth; /* start with empty content */ /* (will collect data until end element) */ pd->lcontent = 0; *pd->content = 0; switch (pd->state) { case STATE_NAME: if (pd->kind) /* if kind is set (non package) */ { strcpy(pd->content, pd->kind); pd->lcontent = strlen(pd->content); pd->content[pd->lcontent++] = ':'; /* prefix name with '<kind>:' */ pd->content[pd->lcontent] = 0; } break; case STATE_PACKAGE: /* solvable name */ pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); if (!strcmp(name, "selection")) pd->kind = "selection"; else if (!strcmp(name, "pattern")) pd->kind = "pattern"; else if (!strcmp(name, "atom")) pd->kind = "atom"; else if (!strcmp(name, "product")) pd->kind = "product"; else if (!strcmp(name, "patch")) pd->kind = "patch"; else pd->kind = NULL; /* default is package */ pd->levrspace = 1; pd->epoch = 0; pd->version = 0; pd->release = 0; pd->freshens = 0; #if 0 fprintf(stderr, "package #%d\n", s - pool->solvables); #endif break; case STATE_UPDATE: pd->levrspace = 1; pd->epoch = 0; pd->version = 0; pd->release = 0; break; case STATE_PROVIDES: /* start of provides */ s->provides = 0; break; case STATE_PROVIDESENTRY: /* entry within provides */ s->provides = adddep(pool, pd, s->provides, atts, 0); break; case STATE_REQUIRESENTRY: s->requires = adddep(pool, pd, s->requires, atts, -SOLVABLE_PREREQMARKER); break; case STATE_PREREQUIRESENTRY: s->requires = adddep(pool, pd, s->requires, atts, SOLVABLE_PREREQMARKER); 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; default: break; } }
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); }
Id repo_add_arch_pkg(Repo *repo, const char *fn, int flags) { Pool *pool = repo->pool; Repodata *data; FILE *fp; struct tarhead th; char line[4096]; int ignoreline; Solvable *s; int l, fd; struct stat stb; void *pkgidhandle = 0; data = repo_add_repodata(repo, flags); 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; } if (fstat(fd, &stb)) { pool_error(pool, -1, "%s: fstat: %s", fn, strerror(errno)); close(fd); return 0; } if (!(fp = solv_xfopen_fd(fn, fd, "r"))) { pool_error(pool, -1, "%s: fdopen failed", fn); close(fd); return 0; } s = 0; inittarhead(&th, fp); while (gettarhead(&th) > 0) { if (th.type != 1 || strcmp(th.path, ".PKGINFO") != 0) { skipentry(&th); continue; } ignoreline = 0; s = pool_id2solvable(pool, repo_add_solvable(repo)); if (flags & ARCH_ADD_WITH_PKGID) pkgidhandle = solv_chksum_create(REPOKEY_TYPE_MD5); while (getsentry(&th, line, sizeof(line))) { l = strlen(line); if (l == 0) continue; if (pkgidhandle) solv_chksum_add(pkgidhandle, line, l); if (line[l - 1] != '\n') { ignoreline = 1; continue; } if (ignoreline) { ignoreline = 0; continue; } line[--l] = 0; if (l == 0 || line[0] == '#') continue; if (!strncmp(line, "pkgname = ", 10)) s->name = pool_str2id(pool, line + 10, 1); else if (!strncmp(line, "pkgver = ", 9)) s->evr = pool_str2id(pool, line + 9, 1); else if (!strncmp(line, "pkgdesc = ", 10)) { repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, line + 10); repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, line + 10); } else if (!strncmp(line, "url = ", 6)) repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, line + 6); else if (!strncmp(line, "builddate = ", 12)) repodata_set_num(data, s - pool->solvables, SOLVABLE_BUILDTIME, strtoull(line + 12, 0, 10)); else if (!strncmp(line, "packager = ", 11)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_PACKAGER, line + 11); else if (!strncmp(line, "size = ", 7)) repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(line + 7, 0, 10)); else if (!strncmp(line, "arch = ", 7)) s->arch = pool_str2id(pool, line + 7, 1); else if (!strncmp(line, "license = ", 10)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_LICENSE, line + 10); else if (!strncmp(line, "replaces = ", 11)) s->obsoletes = adddep(repo, s->obsoletes, line + 11); else if (!strncmp(line, "group = ", 8)) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, line + 8); else if (!strncmp(line, "depend = ", 9)) s->requires = adddep(repo, s->requires, line + 9); else if (!strncmp(line, "optdepend = ", 12)) { char *p = strchr(line, ':'); if (p) *p = 0; s->suggests = adddep(repo, s->suggests, line + 12); } else if (!strncmp(line, "conflict = ", 11)) s->conflicts = adddep(repo, s->conflicts, line + 11); else if (!strncmp(line, "provides = ", 11)) s->provides = adddep(repo, s->provides, line + 11); } break; } freetarhead(&th); fclose(fp); if (!s) { pool_error(pool, -1, "%s: not an arch package", fn); if (pkgidhandle) solv_chksum_free(pkgidhandle, 0); return 0; } if (s && !s->name) { pool_error(pool, -1, "%s: package has no name", fn); repo_free_solvable(repo, s - pool->solvables, 1); s = 0; } if (s) { if (!s->arch) s->arch = ARCH_ANY; if (!s->evr) s->evr = ID_EMPTY; s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (!(flags & REPO_NO_LOCATION)) repodata_set_location(data, s - pool->solvables, 0, 0, fn); if (S_ISREG(stb.st_mode)) repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, (unsigned long long)stb.st_size); if (pkgidhandle) { unsigned char pkgid[16]; solv_chksum_free(pkgidhandle, pkgid); repodata_set_bin_checksum(data, s - pool->solvables, SOLVABLE_PKGID, REPOKEY_TYPE_MD5, pkgid); pkgidhandle = 0; } } if (pkgidhandle) solv_chksum_free(pkgidhandle, 0); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return s ? s - pool->solvables : 0; }
static void XMLCALL startElement(void *userData, const char *name, const char **atts) { struct parsedata *pd = userData; Pool *pool = pd->pool; Solvable *s = pd->solvable; struct stateswitch *sw; #if 0 fprintf(stderr, "start: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { pd->depth++; return; } pd->depth++; if (!pd->swtab[pd->state]) /* no statetable -> no substates */ { #if 0 fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); #endif return; } for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ if (!strcmp(sw->ename, name)) break; if (sw->from != pd->state) { #if 0 fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); #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_PRODUCT: /* parse 'schemeversion' and store in global variable */ { const char * scheme = find_attr("schemeversion", atts); pd->productscheme = (scheme && *scheme) ? atoi(scheme) : -1; } if (!s) { s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); pd->handle = s - pool->solvables; } break; /* <summary lang="xy">... */ case STATE_SUMMARY: case STATE_DESCRIPTION: pd->tmplang = join_dup(&pd->jd, find_attr("lang", atts)); break; case STATE_URL: pd->urltype = pool_str2id(pd->pool, find_attr("name", atts), 1); break; case STATE_REGUPDREPO: { const char *repoid = find_attr("repoid", atts); if (repoid && *repoid) repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_UPDATES_REPOID, repoid); } default: break; } }
static void XMLCALL startElement(void *userData, const char *name, const char **atts) { struct parsedata *pd = userData; Pool *pool = pd->pool; Solvable *solvable = pd->solvable; struct stateswitch *sw; /*const char *str; */ #if 0 fprintf(stderr, "start: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { pd->depth++; return; } pd->depth++; if (!pd->swtab[pd->state]) return; for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ if (!strcmp(sw->ename, name)) break; if (sw->from != pd->state) { #if 0 fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); exit( 1 ); #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_START: break; case STATE_UPDATES: break; /* * <update from="*****@*****.**" * status="stable" * type="bugfix" (enhancement, security) * version="1.4"> */ case STATE_UPDATE: { const char *from = 0, *type = 0, *version = 0; for (; *atts; atts += 2) { if (!strcmp(*atts, "from")) from = atts[1]; else if (!strcmp(*atts, "type")) type = atts[1]; else if (!strcmp(*atts, "version")) version = atts[1]; } solvable = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); pd->datanum = pd->solvable - pool->solvables; solvable->vendor = pool_str2id(pool, from, 1); solvable->evr = pool_str2id(pool, version, 1); solvable->arch = ARCH_NOARCH; if (type) repodata_set_str(pd->data, pd->datanum, SOLVABLE_PATCHCATEGORY, type); pd->buildtime = (time_t)0; } break; /* <id>FEDORA-2007-4594</id> */ case STATE_ID: break; /* <title>imlib-1.9.15-6.fc8</title> */ case STATE_TITLE: break; /* <release>Fedora 8</release> */ case STATE_RELEASE: break; /* <issued date="2008-03-21 21:36:55"/> */ case STATE_ISSUED: case STATE_UPDATED: { const char *date = 0; for (; *atts; atts += 2) { if (!strcmp(*atts, "date")) date = atts[1]; } if (date) { time_t t = datestr2timestamp(date); if (t && t > pd->buildtime) pd->buildtime = t; } } break; case STATE_REFERENCES: break; /* <reference href="https://bugzilla.redhat.com/show_bug.cgi?id=330471" * id="330471" * title="LDAP schema file missing for dhcpd" * type="bugzilla"/> */ case STATE_REFERENCE: { const char *href = 0, *id = 0, *title = 0, *type = 0; Id handle; for (; *atts; atts += 2) { if (!strcmp(*atts, "href")) href = atts[1]; else if (!strcmp(*atts, "id")) id = atts[1]; else if (!strcmp(*atts, "title")) title = atts[1]; else if (!strcmp(*atts, "type")) type = atts[1]; } handle = repodata_new_handle(pd->data); if (href) repodata_set_str(pd->data, handle, UPDATE_REFERENCE_HREF, href); if (id) repodata_set_str(pd->data, handle, UPDATE_REFERENCE_ID, id); if (title) repodata_set_str(pd->data, handle, UPDATE_REFERENCE_TITLE, title); if (type) repodata_set_poolstr(pd->data, handle, UPDATE_REFERENCE_TYPE, type); repodata_add_flexarray(pd->data, pd->datanum, UPDATE_REFERENCE, handle); } break; /* <description>This update ...</description> */ case STATE_DESCRIPTION: break; /* <message type="confirm">This update ...</message> */ case STATE_MESSAGE: break; case STATE_PKGLIST: break; /* <collection short="F8" */ case STATE_COLLECTION: break; /* <name>Fedora 8</name> */ case STATE_NAME: break; /* <package arch="ppc64" name="imlib-debuginfo" release="6.fc8" * src="http://download.fedoraproject.org/pub/fedora/linux/updates/8/ppc64/imlib-debuginfo-1.9.15-6.fc8.ppc64.rpm" * version="1.9.15"> * * * -> patch.conflicts: {name} < {version}.{release} */ case STATE_PACKAGE: { const char *arch = 0, *name = 0; Id evr = makeevr_atts(pool, pd, atts); /* parse "epoch", "version", "release" */ Id n, a = 0; Id rel_id; for (; *atts; atts += 2) { if (!strcmp(*atts, "arch")) arch = atts[1]; else if (!strcmp(*atts, "name")) name = atts[1]; } /* generated Id for name */ n = pool_str2id(pool, name, 1); rel_id = n; if (arch) { /* generate Id for arch and combine with name */ a = pool_str2id(pool, arch, 1); rel_id = pool_rel2id(pool, n, a, REL_ARCH, 1); } rel_id = pool_rel2id(pool, rel_id, evr, REL_LT, 1); solvable->conflicts = repo_addid_dep(pd->repo, solvable->conflicts, rel_id, 0); /* who needs the collection anyway? */ pd->collhandle = repodata_new_handle(pd->data); repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_NAME, n); repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_EVR, evr); repodata_set_id(pd->data, pd->collhandle, UPDATE_COLLECTION_ARCH, a); break; } /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ /* <filename>libntlm-0.4.2-1.fc8.x86_64.rpm</filename> */ case STATE_FILENAME: break; /* <reboot_suggested>True</reboot_suggested> */ case STATE_REBOOT: break; /* <restart_suggested>True</restart_suggested> */ case STATE_RESTART: break; /* <relogin_suggested>True</relogin_suggested> */ case STATE_RELOGIN: break; default: break; } return; }
int repo_add_mdk(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; Repodata *data; Solvable *s; char *buf; int bufa, bufl; data = repo_add_repodata(repo, flags); bufa = 4096; buf = solv_malloc(bufa); bufl = 0; s = 0; while (fgets(buf + bufl, bufa - bufl, fp) > 0) { bufl += strlen(buf + bufl); if (bufl && buf[bufl - 1] != '\n') { if (bufa - bufl < 256) { bufa += 4096; buf = solv_realloc(buf, bufa); } continue; } buf[--bufl] = 0; bufl = 0; if (buf[0] != '@') { pool_debug(pool, SOLV_ERROR, "bad line <%s>\n", buf); continue; } if (!s) s = pool_id2solvable(pool, repo_add_solvable(repo)); if (!strncmp(buf + 1, "filesize@", 9)) repodata_set_num(data, s - pool->solvables, SOLVABLE_DOWNLOADSIZE, strtoull(buf + 10, 0, 10)); else if (!strncmp(buf + 1, "summary@", 8)) repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, buf + 9); else if (!strncmp(buf + 1, "provides@", 9)) s->provides = parse_deps(s, buf + 10, 0); else if (!strncmp(buf + 1, "requires@", 9)) s->requires = parse_deps(s, buf + 10, SOLVABLE_PREREQMARKER); else if (!strncmp(buf + 1, "suggests@", 9)) s->suggests = parse_deps(s, buf + 10, 0); else if (!strncmp(buf + 1, "obsoletes@", 10)) s->obsoletes = parse_deps(s, buf + 11, 0); else if (!strncmp(buf + 1, "conflicts@", 10)) s->conflicts = parse_deps(s, buf + 11, 0); else if (!strncmp(buf + 1, "info@", 5)) { char *nvra = buf + 6; char *epochstr; char *arch; char *version; char *filename; if ((epochstr = strchr(nvra, '@')) != 0) { char *sizestr; *epochstr++ = 0; if ((sizestr = strchr(epochstr, '@')) != 0) { char *groupstr; *sizestr++ = 0; if ((groupstr = strchr(sizestr, '@')) != 0) { char *n; *groupstr++ = 0; if ((n = strchr(groupstr, '@')) != 0) *n = 0; if (*groupstr) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_GROUP, groupstr); } repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(sizestr, 0, 10)); } } filename = pool_tmpjoin(pool, nvra, ".rpm", 0); arch = strrchr(nvra, '.'); if (arch) { *arch++ = 0; s->arch = pool_str2id(pool, arch, 1); } /* argh, do we have a distepoch or not, check self-provides */ if (s->provides) { Id id, lastid, *idp = s->repo->idarraydata + s->provides; lastid = 0; for (idp = s->repo->idarraydata + s->provides; (id = *idp) != 0; idp++) { const char *evr, *name; int namel; Reldep *rd; if (!ISRELDEP(id)) continue; rd = GETRELDEP(pool, id); if (rd->flags != REL_EQ) continue; name = pool_id2str(pool, rd->name); namel = strlen(name); if (strncmp(name, nvra, namel) != 0 || nvra[namel] != '-') continue; evr = pool_id2str(pool, rd->evr); evr = strrchr(evr, '-'); if (evr && strchr(evr, ':') != 0) lastid = id; } if (lastid) { /* self provides found, and it contains a distepoch */ /* replace with self-provides distepoch to get rid of the disttag */ char *nvradistepoch = strrchr(nvra, '-'); if (nvradistepoch) { Reldep *rd = GETRELDEP(pool, lastid); const char *evr = pool_id2str(pool, rd->evr); evr = strrchr(evr, '-'); if (evr && (evr = strchr(evr, ':')) != 0) { if (strlen(evr) < strlen(nvradistepoch)) strcpy(nvradistepoch, evr); } } } } version = strrchr(nvra, '-'); if (version) { char *release = version; *release = 0; version = strrchr(nvra, '-'); *release = '-'; if (!version) version = release; *version++ = 0; } else version = ""; s->name = pool_str2id(pool, nvra, 1); if (epochstr && *epochstr && strcmp(epochstr, "0") != 0) { char *evr = pool_tmpjoin(pool, epochstr, ":", version); s->evr = pool_str2id(pool, evr, 1); } else s->evr = pool_str2id(pool, version, 1); repodata_set_location(data, s - pool->solvables, 0, 0, filename); if (s->name && s->arch != ARCH_SRC && s->arch != ARCH_NOSRC) s->provides = repo_addid_dep(s->repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); s = 0; } else { char *tagend = strchr(buf + 1, '@'); if (tagend) *tagend = 0; pool_debug(pool, SOLV_ERROR, "unknown tag <%s>\n", buf + 1); continue; } } if (s) { pool_debug(pool, SOLV_ERROR, "unclosed package at EOF\n"); repo_free_solvable(s->repo, s - pool->solvables, 1); } solv_free(buf); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; }
/* internal */ static Solvable * get_solvable(HyPackage pkg) { return pool_id2solvable(package_pool(pkg), pkg->id); }
static void XMLCALL startElement(void *userData, const char *name, const char **atts) { struct parsedata *pd = userData; Pool *pool = pd->pool; Solvable *s = pd->solvable; struct stateswitch *sw; #if 0 fprintf(stderr, "start: [%d]%s\n", pd->state, name); #endif if (pd->depth != pd->statedepth) { pd->depth++; return; } pd->depth++; if (!pd->swtab[pd->state]) /* no statetable -> no substates */ { #if 0 fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); #endif return; } for (sw = pd->swtab[pd->state]; sw->from == pd->state; sw++) /* find name in statetable */ if (!strcmp(sw->ename, name)) break; if (sw->from != pd->state) { #if 0 fprintf(stderr, "into unknown: %s (from: %d)\n", name, pd->state); #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_PRODUCT: { /* parse 'type' */ const char *type = find_attr("type", atts, 0); s = pd->solvable = pool_id2solvable(pool, repo_add_solvable(pd->repo)); repodata_extend(pd->data, s - pool->solvables); pd->handle = s - pool->solvables; if (type) { repodata_set_str(pd->data, pd->handle, PRODUCT_TYPE, type); } } break; case STATE_VERSION: { const char *ver = find_attr("ver", atts, 0); const char *rel = find_attr("rel", atts, 0); /* const char *epoch = find_attr("epoch", atts, 1); ignored */ s->evr = makeevr(pd->pool, join2(ver, "-", rel)); } break; /* <summary lang="xy">... */ case STATE_SUMMARY: pd->tmplang = find_attr("lang", atts, 1); break; default: break; } }