void repo_add_products(Repo *repo, const char *proddir, const char *root, int flags) { const char *fullpath; DIR *dir; dir = opendir(proddir); if (dir) { /* assume code11 stype products */ closedir(dir); repo_add_code11_products(repo, proddir, flags); return; } /* code11 didn't work, try old zyppdb */ fullpath = root ? join2(root, "", "/var/lib/zypp/db/products") : "/var/lib/zypp/db/products"; dir = opendir(fullpath); if (dir) { closedir(dir); /* assume code10 style products */ repo_add_zyppdb_products(repo, fullpath, flags); join_freemem(); return; } /* code11 didn't work, try -release files parsing */ fullpath = root ? join2(root, "", "/etc") : "/etc"; dir = opendir(fullpath); if (dir) { closedir(dir); repo_add_releasefile_products(repo, fullpath, flags); join_freemem(); return; } /* no luck. print an error message in case the root argument is wrong */ perror(fullpath); join_freemem(); /* the least we can do... */ if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) repodata_internalize(repo_last_repodata(repo)); }
void repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags) { int i; struct parsedata pd; struct stateswitch *sw; struct dirent *entry; char *fullpath; DIR *dir; FILE *fp; Repodata *data; data = repo_add_repodata(repo, flags); memset(&pd, 0, sizeof(pd)); pd.repo = repo; pd.pool = repo->pool; pd.data = data; pd.content = malloc(256); pd.acontent = 256; 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; } dir = opendir(dirpath); if (dir) { while ((entry = readdir(dir))) { if (strlen(entry->d_name) < 3) continue; /* skip '.' and '..' */ fullpath = join2(dirpath, "/", entry->d_name); if ((fp = fopen(fullpath, "r")) == 0) { perror(fullpath); continue; } add_zyppdb_product(&pd, fp); fclose(fp); } } closedir(dir); solv_free((void *)pd.tmplang); free(pd.content); join_freemem(); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); }
int repo_add_zyppdb_products(Repo *repo, const char *dirpath, int flags) { struct parsedata pd; struct dirent *entry; char *fullpath; DIR *dir; FILE *fp; Repodata *data; data = repo_add_repodata(repo, flags); memset(&pd, 0, sizeof(pd)); pd.repo = repo; pd.pool = repo->pool; pd.data = data; solv_xmlparser_init(&pd.xmlp, stateswitches, &pd, startElement, endElement); if (flags & REPO_USE_ROOTDIR) dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (dir) { while ((entry = readdir(dir))) { if (entry->d_name[0] == '.') continue; /* skip dot files */ fullpath = join2(&pd.jd, dirpath, "/", entry->d_name); if ((fp = fopen(fullpath, "r")) == 0) { pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno)); continue; } pd.filename = entry->d_name; if (solv_xmlparser_parse(&pd.xmlp, fp) != SOLV_XMLPARSER_OK) { pool_debug(pd.pool, SOLV_ERROR, "repo_zyppdb: %s: %s at line %u:%u\n", pd.filename, pd.xmlp.errstr, pd.xmlp.line, pd.xmlp.column); pd.solvable = solvable_free(pd.solvable, 1); } fclose(fp); } } closedir(dir); solv_xmlparser_free(&pd.xmlp); join_freemem(&pd.jd); if (flags & REPO_USE_ROOTDIR) solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; }
int repo_add_updateinfoxml(Repo *repo, FILE *fp, int flags) { Pool *pool = repo->pool; struct parsedata pd; char buf[BUFF_SIZE]; int i, l; struct stateswitch *sw; Repodata *data; XML_Parser parser; 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.pool = pool; pd.repo = repo; pd.data = data; pd.content = malloc(256); pd.acontent = 256; pd.lcontent = 0; parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &pd); 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_updateinfoxml: %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); free(pd.content); join_freemem(&pd.jd); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; }
int repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags) { DIR *dir; struct dirent *entry; FILE *fp; char *fullpath; struct parsedata pd; if (!dirpath) dirpath = "/etc"; if (flags & REPO_USE_ROOTDIR) dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (!dir) { if (flags & REPO_USE_ROOTDIR) solv_free((char *)dirpath); return 0; } memset(&pd, 0, sizeof(pd)); pd.repo = repo; while ((entry = readdir(dir))) { int len = strlen(entry->d_name); if (len > 8 && !strcmp(entry->d_name + len - 8, "-release")) { /* skip /etc/lsb-release, thats not a product per-se */ if (strcmp(entry->d_name, "lsb-release") == 0) continue; fullpath = join2(&pd.jd, dirpath, "/", entry->d_name); if ((fp = fopen(fullpath, "r")) == 0) { pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno)); continue; } add_releasefile_product(&pd, fp); fclose(fp); } } closedir(dir); join_freemem(&pd.jd); if (flags & REPO_USE_ROOTDIR) solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) repodata_internalize(repo_last_repodata(repo)); return 0; }
int repo_add_releasefile_products(Repo *repo, const char *dirpath, int flags) { DIR *dir; struct dirent *entry; FILE *fp; char *fullpath; dir = opendir(dirpath); if (!dir) return 0; while ((entry = readdir(dir))) { int len = strlen(entry->d_name); if (len > 8 && !strcmp(entry->d_name + len - 8, "-release")) { /* skip /etc/lsb-release, thats not a product per-se */ if (strcmp(entry->d_name, "lsb-release") == 0) continue; fullpath = join2(dirpath, "/", entry->d_name); if ((fp = fopen(fullpath, "r")) == 0) { perror(fullpath); continue; } add_releasefile_product(repo, fp); fclose(fp); } } closedir(dir); join_freemem(); if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) repodata_internalize(repo_last_repodata(repo)); return 0; }
void 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; now = sat_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 = sat_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 (!sat_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 = sat_zextend(pd.cscache, pd.ncscache, index + 1 - pd.ncscache, sizeof(Id), 255); pd.ncscache = index + 1; } pd.cscache[index] = di.solvid; } dataiterator_free(&di); } XML_Parser 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, SAT_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); sat_free(pd.content); sat_free(pd.lastdirstr); join_freemem(); stringpool_free(&pd.cspool); sat_free(pd.cscache); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); POOL_DEBUG(SAT_DEBUG_STATS, "repo_add_rpmmd took %d ms\n", sat_timems(now)); POOL_DEBUG(SAT_DEBUG_STATS, "repo size: %d solvables\n", repo->nsolvables); POOL_DEBUG(SAT_DEBUG_STATS, "repo memory used: %d K incore, %d K idarray\n", data->incoredatalen/1024, repo->idarraysize / (int)(1024/sizeof(Id))); }
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; }
int repo_add_code11_products(Repo *repo, const char *dirpath, int flags) { Repodata *data; struct parsedata pd; struct stateswitch *sw; DIR *dir; int i; data = repo_add_repodata(repo, flags); memset(&pd, 0, sizeof(pd)); pd.repo = repo; pd.pool = repo->pool; pd.data = data; pd.content = solv_malloc(256); pd.acontent = 256; 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; } if (flags & REPO_USE_ROOTDIR) dirpath = pool_prepend_rootdir(repo->pool, dirpath); dir = opendir(dirpath); if (dir) { struct dirent *entry; struct stat st; char *fullpath; /* check for <productsdir>/baseproduct on code11 and remember its target inode */ if (stat(join2(&pd.jd, dirpath, "/", "baseproduct"), &st) == 0) /* follow symlink */ pd.baseproduct = st.st_ino; else pd.baseproduct = 0; while ((entry = readdir(dir))) { int len = strlen(entry->d_name); FILE *fp; if (len <= 5 || strcmp(entry->d_name + len - 5, ".prod") != 0) continue; fullpath = join2(&pd.jd, dirpath, "/", entry->d_name); fp = fopen(fullpath, "r"); if (!fp) { pool_error(repo->pool, 0, "%s: %s", fullpath, strerror(errno)); continue; } pd.filename = fullpath; pd.basename = entry->d_name; add_code11_product(&pd, fp); fclose(fp); } closedir(dir); } solv_free(pd.content); join_freemem(&pd.jd); if (flags & REPO_USE_ROOTDIR) solv_free((char *)dirpath); if (!(flags & REPO_NO_INTERNALIZE)) repodata_internalize(data); return 0; }