const unsigned char * solv_chksum_get(Chksum *chk, int *lenp) { if (chk->done) { if (lenp) *lenp = solv_chksum_len(chk->type); return chk->result; } switch(chk->type) { case REPOKEY_TYPE_MD5: solv_MD5_Final(chk->result, &chk->c.md5); chk->done = 1; if (lenp) *lenp = 16; return chk->result; case REPOKEY_TYPE_SHA1: solv_SHA1_Final(&chk->c.sha1, chk->result); chk->done = 1; if (lenp) *lenp = 20; return chk->result; case REPOKEY_TYPE_SHA224: solv_SHA224_Final(chk->result, &chk->c.sha224); chk->done = 1; if (lenp) *lenp = 28; return chk->result; case REPOKEY_TYPE_SHA256: solv_SHA256_Final(chk->result, &chk->c.sha256); chk->done = 1; if (lenp) *lenp = 32; return chk->result; case REPOKEY_TYPE_SHA384: solv_SHA384_Final(chk->result, &chk->c.sha384); chk->done = 1; if (lenp) *lenp = 48; return chk->result; case REPOKEY_TYPE_SHA512: solv_SHA512_Final(chk->result, &chk->c.sha512); chk->done = 1; if (lenp) *lenp = 64; return chk->result; default: if (lenp) *lenp = 0; return 0; } }
void * solv_chksum_create_from_bin(Id type, const unsigned char *buf) { struct ctxhandle *h; int l = solv_chksum_len(type); if (buf == 0 || l == 0) return 0; h = solv_calloc(1, sizeof(*h)); h->type = type; h->done = 1; memcpy(h->result, buf, l); return h; }
Chksum * solv_chksum_create_from_bin(Id type, const unsigned char *buf) { Chksum *chk; int l = solv_chksum_len(type); if (buf == 0 || l == 0) return 0; chk = solv_calloc(1, sizeof(*chk)); chk->type = type; chk->done = 1; memcpy(chk->result, buf, l); return chk; }
static void set_checksum(struct parsedata *pd, Repodata *data, Id handle, Id keyname, char *line) { char *sp[3]; Id type; if (split(line, sp, 3) != 2) { pd->ret = pool_error(pd->pool, -1, "susetags: line %d: bad checksum line '%s'\n", pd->lineno, line); return; } type = solv_chksum_str2type(sp[0]); if (!type) { pd->ret = pool_error(pd->pool, -1, "susetags: line %d: unknown checksum type: '%s'\n", pd->lineno, sp[0]); return; } if (strlen(sp[1]) != 2 * solv_chksum_len(type)) { pd->ret = pool_error(pd->pool, -1, "susetags: line %d: bad checksum length for type %s: '%s'\n", pd->lineno, sp[0], sp[1]); return; } repodata_set_checksum(data, handle, keyname, type, sp[1]); }
const unsigned char * solv_chksum_get(void *handle, int *lenp) { struct ctxhandle *h = handle; if (h->done) { if (lenp) *lenp = solv_chksum_len(h->type); return h->result; } switch(h->type) { case REPOKEY_TYPE_MD5: solv_MD5_Final(h->result, &h->c.md5); h->done = 1; if (lenp) *lenp = 16; return h->result; case REPOKEY_TYPE_SHA1: solv_SHA1_Final(&h->c.sha1, h->result); h->done = 1; if (lenp) *lenp = 20; return h->result; case REPOKEY_TYPE_SHA256: solv_SHA256_Final(h->result, &h->c.sha256); h->done = 1; if (lenp) *lenp = 32; return h->result; default: if (lenp) *lenp = 0; 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; int res = 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 ("REPOKEYWORDS")) { add_multiple_strings(data, SOLVID_META, REPOSITORY_KEYWORDS, value); continue; } if (istag ("DISTRO")) { Id dh = repodata_new_handle(data); char *p; /* like with createrepo --distro */ if ((p = strchr(value, ',')) != 0) { *p++ = 0; if (*value) repodata_set_poolstr(data, dh, REPOSITORY_PRODUCT_CPEID, value); } else p = value; if (*p) repodata_set_str(data, dh, REPOSITORY_PRODUCT_LABEL, p); repodata_add_flexarray(data, SOLVID_META, REPOSITORY_DISTROS, dh); 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) { pool_error(pool, -1, "%s: unknown checksum type '%s'", value, checksumtype); res = 1; continue; } l = solv_chksum_len(type); if (strlen(checksum) != 2 * l) { pool_error(pool, -1, "%s: invalid checksum length for %s", value, checksumtype); res = 1; 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)); 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)); 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_poolstr(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); } } } if (!code10) continue; /* * Every tag below is Code10 only * */ if (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 (istag ("PREREQUIRES")) s->requires = adddep(pool, &pd, s->requires, value, SOLVABLE_PREREQMARKER); else if (istag ("REQUIRES")) s->requires = adddep(pool, &pd, s->requires, value, -SOLVABLE_PREREQMARKER); else if (istag ("PROVIDES")) s->provides = adddep(pool, &pd, s->provides, value, 0); else if (istag ("CONFLICTS")) s->conflicts = adddep(pool, &pd, s->conflicts, value, 0); else if (istag ("OBSOLETES")) s->obsoletes = adddep(pool, &pd, s->obsoletes, value, 0); else if (istag ("RECOMMENDS")) s->recommends = adddep(pool, &pd, s->recommends, value, 0); else if (istag ("SUGGESTS")) s->suggests = adddep(pool, &pd, s->suggests, value, 0); else if (istag ("SUPPLEMENTS")) s->supplements = adddep(pool, &pd, s->supplements, value, 0); else if (istag ("ENHANCES")) s->enhances = adddep(pool, &pd, s->enhances, value, 0); /* FRESHENS doesn't seem to exist. */ else if (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_ERROR, "repo_content: 'content' incomplete, no product solvable created!\n"); repo_free_solvable(repo, s - pool->solvables, 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)); 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); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return res; }
static void XMLCALL endElement(void *userData, const char *name) { //fprintf(stderr,"-tag: %s\n", name); struct parsedata *pd = userData; Pool *pool = pd->common.pool; Solvable *s = pd->solvable; Repo *repo = pd->common.repo; Id handle = pd->handle; Id id; char *p; if (pd->depth != pd->statedepth) { pd->depth--; // printf("back from unknown %d %d %d\n", pd->state, pd->depth, pd->statedepth); return; } /* ignore patterns & metadata */ 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--; pd->statedepth--; switch (pd->state) { case STATE_SOLVABLE: if (pd->kind && !s->name) /* add namespace in case of NULL name */ s->name = pool_str2id(pool, join2(pd->kind, ":", ""), 1); if (!s->arch) s->arch = ARCH_NOARCH; if (!s->evr) s->evr = ID_EMPTY; /* some patterns have this */ 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); s->supplements = repo_fix_supplements(repo, s->provides, s->supplements, pd->freshens); s->conflicts = repo_fix_conflicts(repo, s->conflicts); pd->freshens = 0; pd->kind = 0; break; case STATE_NAME: if (pd->kind) s->name = pool_str2id(pool, join2(pd->kind, ":", pd->content), 1); else s->name = pool_str2id(pool, pd->content, 1); break; case STATE_ARCH: s->arch = pool_str2id(pool, pd->content, 1); break; case STATE_VENDOR: s->vendor = pool_str2id(pool, pd->content, 1); break; case STATE_RPM_GROUP: repodata_set_poolstr(pd->data, handle, SOLVABLE_GROUP, pd->content); break; case STATE_RPM_LICENSE: repodata_set_poolstr(pd->data, handle, SOLVABLE_LICENSE, pd->content); break; case STATE_CHECKSUM: { Id type, index; type = solv_chksum_str2type(pd->tmpattr); if (!type) { fprintf(stderr, "Unknown checksum type: %d: %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr); exit(1); } if (strlen(pd->content) != 2 * solv_chksum_len(type)) { fprintf(stderr, "Invalid checksum length: %d: for %s\n", (unsigned int)XML_GetCurrentLineNumber(*pd->parser), pd->tmpattr); exit(1); } repodata_set_checksum(pd->data, handle, SOLVABLE_CHECKSUM, type, pd->content); /* we save the checksum to solvable id relationship for extended metadata */ index = stringpool_str2id(&pd->cspool, pd->content, 1 /* create it */); if (index >= pd->ncscache) { pd->cscache = solv_zextend(pd->cscache, pd->ncscache, index + 1 - pd->ncscache, sizeof(Id), 255); pd->ncscache = index + 1; } /* add the checksum to the cache */ pd->cscache[index] = s - pool->solvables; break; } case STATE_FILE: #if 0 id = pool_str2id(pool, pd->content, 1); s->provides = repo_addid_dep(repo, s->provides, id, SOLVABLE_FILEMARKER); #endif if ((p = strrchr(pd->content, '/')) != 0) { *p++ = 0; if (pd->lastdir && !strcmp(pd->lastdirstr, pd->content)) { id = pd->lastdir; } else { int l; id = repodata_str2dir(pd->data, pd->content, 1); l = strlen(pd->content) + 1; if (l > pd->lastdirstrl) { pd->lastdirstrl = l + 128; pd->lastdirstr = solv_realloc(pd->lastdirstr, pd->lastdirstrl); } strcpy(pd->lastdirstr, pd->content); pd->lastdir = id; } } else { p = pd->content; id = 0; } if (!id) id = repodata_str2dir(pd->data, "/", 1); repodata_add_dirstr(pd->data, handle, SOLVABLE_FILELIST, id, p); break; case STATE_SUMMARY: repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_SUMMARY, pd->tmplang), pd->content); break; case STATE_DESCRIPTION: set_description_author(pd->data, handle, pd->content, pd); break; case STATE_CATEGORY: repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_CATEGORY, pd->tmplang), pd->content); break; case STATE_DISTRIBUTION: repodata_set_poolstr(pd->data, handle, SOLVABLE_DISTRIBUTION, pd->content); break; case STATE_URL: if (pd->content[0]) repodata_set_str(pd->data, handle, SOLVABLE_URL, pd->content); break; case STATE_PACKAGER: if (pd->content[0]) repodata_set_poolstr(pd->data, handle, SOLVABLE_PACKAGER, pd->content); break; case STATE_SOURCERPM: set_sourcerpm(pd->data, s, handle, pd->content); break; case STATE_RELNOTESURL: if (pd->content[0]) { repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pool_str2id(pool, "releasenotes", 1)); } break; case STATE_UPDATEURL: if (pd->content[0]) { repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pool_str2id(pool, "update", 1)); } break; case STATE_OPTIONALURL: if (pd->content[0]) { repodata_add_poolstr_array(pd->data, pd->handle, PRODUCT_URL, pd->content); repodata_add_idarray(pd->data, pd->handle, PRODUCT_URL_TYPE, pool_str2id(pool, "optional", 1)); } break; case STATE_FLAG: if (pd->content[0]) repodata_set_poolstr(pd->data, handle, PRODUCT_FLAGS, pd->content); break; case STATE_EULA: if (pd->content[0]) repodata_set_str(pd->data, handle, langtag(pd, SOLVABLE_EULA, pd->tmplang), pd->content); break; case STATE_KEYWORD: if (pd->content[0]) repodata_add_poolstr_array(pd->data, pd->handle, SOLVABLE_KEYWORDS, pd->content); break; case STATE_DISKUSAGE: if (pd->ndirs) commit_diskusage(pd, pd->handle); break; case STATE_ORDER: if (pd->content[0]) repodata_set_str(pd->data, pd->handle, SOLVABLE_ORDER, pd->content); default: break; } pd->state = pd->sbtab[pd->state]; pd->docontent = 0; // fprintf(stderr, "back from known %d %d %d\n", pd->state, pd->depth, pd->statedepth); }
int repo_add_rpmmd(Repo *repo, FILE *fp, const char *language, int flags) { Pool *pool = repo->pool; struct parsedata pd; char buf[BUFF_SIZE]; int i, l; struct stateswitch *sw; Repodata *data; unsigned int now; XML_Parser parser; now = solv_timems(0); data = repo_add_repodata(repo, flags); memset(&pd, 0, sizeof(pd)); for (i = 0, sw = stateswitches; sw->from != NUMSTATES; i++, sw++) { if (!pd.swtab[sw->from]) pd.swtab[sw->from] = sw; pd.sbtab[sw->to] = sw->from; } pd.common.pool = pool; pd.common.repo = repo; pd.data = data; pd.content = solv_malloc(256); pd.acontent = 256; pd.lcontent = 0; pd.common.tmp = 0; pd.common.tmpl = 0; pd.kind = 0; pd.language = language; /* initialize the string pool where we will store the package checksums we know about, to get an Id we can use in a cache */ stringpool_init_empty(&pd.cspool); if ((flags & REPO_EXTEND_SOLVABLES) != 0) { /* setup join data */ Dataiterator di; dataiterator_init(&di, pool, repo, 0, SOLVABLE_CHECKSUM, 0, 0); while (dataiterator_step(&di)) { const char *str; int index; if (!solv_chksum_len(di.key->type)) continue; str = repodata_chk2str(di.data, di.key->type, (const unsigned char *)di.kv.str); index = stringpool_str2id(&pd.cspool, str, 1); if (index >= pd.ncscache) { pd.cscache = solv_zextend(pd.cscache, pd.ncscache, index + 1 - pd.ncscache, sizeof(Id), 255); pd.ncscache = index + 1; } pd.cscache[index] = di.solvid; } dataiterator_free(&di); } parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &pd); pd.parser = &parser; XML_SetElementHandler(parser, startElement, endElement); XML_SetCharacterDataHandler(parser, characterData); for (;;) { l = fread(buf, 1, sizeof(buf), fp); if (XML_Parse(parser, buf, l, l == 0) == XML_STATUS_ERROR) { pool_debug(pool, SOLV_FATAL, "repo_rpmmd: %s at line %u:%u\n", XML_ErrorString(XML_GetErrorCode(parser)), (unsigned int)XML_GetCurrentLineNumber(parser), (unsigned int)XML_GetCurrentColumnNumber(parser)); exit(1); } if (l == 0) break; } XML_ParserFree(parser); solv_free(pd.content); solv_free(pd.lastdirstr); join_freemem(); stringpool_free(&pd.cspool); solv_free(pd.cscache); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); POOL_DEBUG(SOLV_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", solv_timems(now)); POOL_DEBUG(SOLV_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); POOL_DEBUG(SOLV_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", data->incoredatalen/1024, repo->idarraysize / (int)(1024/sizeof(Id))); return 0; }
/* warning: does inplace changes */ static void control2solvable(Solvable *s, Repodata *data, char *control) { Repo *repo = s->repo; Pool *pool = repo->pool; char *p, *q, *end, *tag; int x, l; int havesource = 0; char checksum[32 * 2 + 1]; Id checksumtype = 0; Id newtype; p = control; while (*p) { p = strchr(p, '\n'); if (!p) break; if (p[1] == ' ' || p[1] == '\t') { char *q; /* continuation line */ q = p - 1; while (q >= control && *q == ' ' && *q == '\t') q--; l = q + 1 - control; if (l) memmove(p + 1 - l, control, l); control = p + 1 - l; p[1] = '\n'; p += 2; continue; } end = p - 1; if (*p) *p++ = 0; /* strip trailing space */ while (end >= control && (*end == ' ' || *end == '\t')) *end-- = 0; tag = control; control = p; q = strchr(tag, ':'); if (!q || q - tag < 4) continue; *q++ = 0; while (*q == ' ' || *q == '\t') q++; x = '@' + (tag[0] & 0x1f); x = (x << 8) + '@' + (tag[1] & 0x1f); switch(x) { case 'A' << 8 | 'R': if (!strcasecmp(tag, "architecture")) s->arch = pool_str2id(pool, q, 1); break; case 'B' << 8 | 'R': if (!strcasecmp(tag, "breaks")) s->conflicts = makedeps(repo, q, s->conflicts, 0); break; case 'C' << 8 | 'O': if (!strcasecmp(tag, "conflicts")) s->conflicts = makedeps(repo, q, s->conflicts, 0); break; case 'D' << 8 | 'E': if (!strcasecmp(tag, "depends")) s->requires = makedeps(repo, q, s->requires, -SOLVABLE_PREREQMARKER); else if (!strcasecmp(tag, "description")) { char *ld = strchr(q, '\n'); if (ld) { *ld++ = 0; repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, ld); } else repodata_set_str(data, s - pool->solvables, SOLVABLE_DESCRIPTION, q); repodata_set_str(data, s - pool->solvables, SOLVABLE_SUMMARY, q); } break; case 'E' << 8 | 'N': if (!strcasecmp(tag, "enhances")) s->enhances = makedeps(repo, q, s->enhances, 0); break; case 'F' << 8 | 'I': if (!strcasecmp(tag, "filename")) repodata_set_location(data, s - pool->solvables, 0, 0, q); break; case 'H' << 8 | 'O': if (!strcasecmp(tag, "homepage")) repodata_set_str(data, s - pool->solvables, SOLVABLE_URL, q); break; case 'I' << 8 | 'N': if (!strcasecmp(tag, "installed-size")) repodata_set_num(data, s - pool->solvables, SOLVABLE_INSTALLSIZE, strtoull(q, 0, 10) << 10); break; case 'M' << 8 | 'D': if (!strcasecmp(tag, "md5sum") && !checksumtype && strlen(q) == 16 * 2) { strcpy(checksum, q); checksumtype = REPOKEY_TYPE_MD5; } break; case 'P' << 8 | 'A': if (!strcasecmp(tag, "package")) s->name = pool_str2id(pool, q, 1); break; case 'P' << 8 | 'R': if (!strcasecmp(tag, "pre-depends")) s->requires = makedeps(repo, q, s->requires, SOLVABLE_PREREQMARKER); else if (!strcasecmp(tag, "provides")) s->provides = makedeps(repo, q, s->provides, 0); break; case 'R' << 8 | 'E': if (!strcasecmp(tag, "replaces")) s->obsoletes = makedeps(repo, q, s->obsoletes, 0); else if (!strcasecmp(tag, "recommends")) s->recommends = makedeps(repo, q, s->recommends, 0); break; case 'S' << 8 | 'H': newtype = solv_chksum_str2type(tag); if (!newtype || solv_chksum_len(newtype) * 2 != strlen(q)) break; if (!checksumtype || (newtype == REPOKEY_TYPE_SHA1 && checksumtype != REPOKEY_TYPE_SHA256) || newtype == REPOKEY_TYPE_SHA256) { strcpy(checksum, q); checksumtype = newtype; } break; case 'S' << 8 | 'O': if (!strcasecmp(tag, "source")) { char *q2; /* ignore version for now */ for (q2 = q; *q2; q2++) if (*q2 == ' ' || *q2 == '\t') { *q2 = 0; break; } if (s->name && !strcmp(q, pool_id2str(pool, s->name))) repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME); else repodata_set_id(data, s - pool->solvables, SOLVABLE_SOURCENAME, pool_str2id(pool, q, 1)); havesource = 1; } break; case 'S' << 8 | 'T': if (!strcasecmp(tag, "status")) repodata_set_poolstr(data, s - pool->solvables, SOLVABLE_INSTALLSTATUS, q); break; case 'S' << 8 | 'U': if (!strcasecmp(tag, "suggests")) s->suggests = makedeps(repo, q, s->suggests, 0); break; case 'V' << 8 | 'E': if (!strcasecmp(tag, "version")) s->evr = pool_str2id(pool, q, 1); break; } } if (checksumtype) repodata_set_checksum(data, s - pool->solvables, SOLVABLE_CHECKSUM, checksumtype, checksum); if (!s->arch) s->arch = ARCH_ALL; if (!s->evr) s->evr = ID_EMPTY; if (s->name) s->provides = repo_addid_dep(repo, s->provides, pool_rel2id(pool, s->name, s->evr, REL_EQ, 1), 0); if (s->name && !havesource) repodata_set_void(data, s - pool->solvables, SOLVABLE_SOURCENAME); if (s->obsoletes) { /* obsoletes only count when the packages also conflict */ /* XXX: should not transcode here */ int i, j, k; Id d, cid; for (i = j = s->obsoletes; (d = repo->idarraydata[i]) != 0; i++) { if (!s->conflicts) continue; for (k = s->conflicts; (cid = repo->idarraydata[k]) != 0; k++) { if (repo->idarraydata[k] == cid) break; if (ISRELDEP(cid)) { Reldep *rd = GETRELDEP(pool, cid); if (rd->flags < 8 && rd->name == d) break; /* specialize obsoletes */ } } if (cid) repo->idarraydata[j++] = cid; } repo->idarraydata[j] = 0; if (j == s->obsoletes) s->obsoletes = 0; } }
const char * repo_lookup_checksum(Repo *repo, Id entry, Id keyname, Id *typep) { const unsigned char *chk = repo_lookup_bin_checksum(repo, entry, keyname, typep); return chk ? pool_bin2hex(repo->pool, chk, solv_chksum_len(*typep)) : 0; }
static int dump_attr(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv) { const char *keyname; KeyValue *kvp; int indent = 0; keyname = pool_id2str(repo->pool, key->name); for (kvp = kv; (kvp = kvp->parent) != 0; indent += 2) printf(" "); switch(key->type) { case REPOKEY_TYPE_ID: if (data && data->localpool) kv->str = stringpool_id2str(&data->spool, kv->id); else kv->str = pool_dep2str(repo->pool, kv->id); printf("%s: %s\n", keyname, kv->str); break; case REPOKEY_TYPE_CONSTANTID: printf("%s: %s\n", keyname, pool_dep2str(repo->pool, kv->id)); break; case REPOKEY_TYPE_IDARRAY: if (!kv->entry) printf("%s:\n%*s", keyname, indent, ""); if (data && data->localpool) printf(" %s\n", stringpool_id2str(&data->spool, kv->id)); else printf(" %s\n", pool_dep2str(repo->pool, kv->id)); break; case REPOKEY_TYPE_STR: printf("%s: %s\n", keyname, kv->str); break; case REPOKEY_TYPE_VOID: printf("%s: (void)\n", keyname); break; case REPOKEY_TYPE_CONSTANT: printf("%s: %u\n", keyname, kv->num); break; case REPOKEY_TYPE_NUM: printf("%s: %llu\n", keyname, SOLV_KV_NUM64(kv)); break; case REPOKEY_TYPE_BINARY: if (kv->num) printf("%s: %02x..%02x len %u\n", keyname, (unsigned char)kv->str[0], (unsigned char)kv->str[kv->num - 1], kv->num); else printf("%s: len 0\n", keyname); break; case REPOKEY_TYPE_DIRNUMNUMARRAY: if (!kv->entry) printf("%s:\n%*s", keyname, indent, ""); printf(" %s %u %u\n", repodata_dir2str(data, kv->id, 0), kv->num, kv->num2); break; case REPOKEY_TYPE_DIRSTRARRAY: if (!kv->entry) printf("%s:\n%*s", keyname, indent, ""); printf(" %s\n", repodata_dir2str(data, kv->id, kv->str)); break; case REPOKEY_TYPE_FIXARRAY: case REPOKEY_TYPE_FLEXARRAY: if (!kv->entry) printf("%s:\n", keyname); else printf("\n"); break; default: if (solv_chksum_len(key->type)) { printf("%s: %s (%s)\n", keyname, repodata_chk2str(data, key->type, (unsigned char *)kv->str), solv_chksum_type2str(key->type)); break; } printf("%s: ?\n", keyname); break; } return 0; }
static int dump_attr_json(Repo *repo, Repodata *data, Repokey *key, KeyValue *kv, struct cbdata *cbdata) { Pool *pool = repo->pool; const char *keyname; KeyValue *kvp; int indent = cbdata->baseindent; int isarray = 0; const char *str; int depth = 0; keyname = pool_id2str(repo->pool, key->name); for (kvp = kv; (kvp = kvp->parent) != 0; indent += 4) depth++; if (cbdata->nfirst < depth + 1) { cbdata->first = solv_realloc(cbdata->first, depth + 16); memset(cbdata->first + cbdata->nfirst, 0, depth + 16 - cbdata->nfirst); cbdata->nfirst = depth + 16; } switch(key->type) { case REPOKEY_TYPE_IDARRAY: case REPOKEY_TYPE_DIRNUMNUMARRAY: case REPOKEY_TYPE_DIRSTRARRAY: isarray = 1; break; case REPOKEY_TYPE_FIXARRAY: case REPOKEY_TYPE_FLEXARRAY: isarray = 2; break; default: break; } if (!isarray || !kv->entry) { if (cbdata->first[depth]) printf(",\n"); printf("%*s%s: ", indent, "", jsonstring(pool, keyname)); cbdata->first[depth] = 1; } if (isarray == 1 && !kv->entry) printf("[\n%*s", indent + 2, ""); else if (isarray == 1 && kv->entry) printf("%*s", indent + 2, ""); switch(key->type) { case REPOKEY_TYPE_ID: if (data && data->localpool) str = stringpool_id2str(&data->spool, kv->id); else str = pool_dep2str(repo->pool, kv->id); printf("%s", jsonstring(pool, str)); break; case REPOKEY_TYPE_CONSTANTID: str = pool_dep2str(repo->pool, kv->id); printf("%s", jsonstring(pool, str)); break; case REPOKEY_TYPE_IDARRAY: if (data && data->localpool) str = stringpool_id2str(&data->spool, kv->id); else str = pool_dep2str(repo->pool, kv->id); printf("%s", jsonstring(pool, str)); break; case REPOKEY_TYPE_STR: str = kv->str; printf("%s", jsonstring(pool, str)); break; case REPOKEY_TYPE_VOID: printf("null"); break; case REPOKEY_TYPE_CONSTANT: printf("%u", kv->num); break; case REPOKEY_TYPE_NUM: printf("%llu", SOLV_KV_NUM64(kv)); break; case REPOKEY_TYPE_BINARY: printf("\"<binary>\""); break; case REPOKEY_TYPE_DIRNUMNUMARRAY: printf("{\n"); printf("%*s \"dir\": %s,\n", indent, "", jsonstring(pool, repodata_dir2str(data, kv->id, 0))); printf("%*s \"num1\": %u,\n", indent, "", kv->num); printf("%*s \"num2\": %u\n", indent, "", kv->num2); printf("%*s }", indent, ""); break; case REPOKEY_TYPE_DIRSTRARRAY: printf("%s", jsonstring(pool, repodata_dir2str(data, kv->id, kv->str))); break; case REPOKEY_TYPE_FIXARRAY: case REPOKEY_TYPE_FLEXARRAY: cbdata->first[depth + 1] = 0; if (!kv->entry) printf("[\n"); else { if (kv->eof != 2) printf("\n%*s },\n", indent, ""); else printf("\n%*s }\n", indent, ""); } if (kv->eof != 2) printf("%*s {\n", indent, ""); else printf("%*s]", indent, ""); break; default: if (solv_chksum_len(key->type)) { printf("{\n"); printf("%*s \"value\": %s,\n", indent, "", jsonstring(pool, repodata_chk2str(data, key->type, (unsigned char *)kv->str))); printf("%*s \"type\": %s\n", indent, "", jsonstring(pool, solv_chksum_type2str(key->type))); printf("%*s}", indent, ""); break; } printf("\"?\""); break; } if (isarray == 1) { if (!kv->eof) printf(",\n"); else printf("\n%*s]", indent, ""); } return 0; }