FILE * solv_xfopen_buf(const char *fn, char **bufp, size_t *buflp, const char *mode) { struct bufcookie *bc; FILE *fp; if (*mode != 'r' && *mode != 'w') return 0; bc = solv_calloc(1, sizeof(*bc)); bc->freemem = 0; bc->bufp = bufp; if (!buflp) { bc->bufl_int = *mode == 'w' ? 0 : strlen(*bufp); buflp = &bc->bufl_int; } bc->buflp = buflp; if (*mode == 'w') { *bc->bufp = solv_extend(0, 0, 1, 1, 4095); /* always zero-terminate */ (*bc->bufp)[0] = 0; *bc->buflp = 0; } fp = cookieopen(bc, mode, cookie_bufread, cookie_bufwrite, cookie_bufclose); if (!strcmp(mode, "rf")) /* auto-free */ bc->freemem = *bufp; if (!fp) { if (*mode == 'w') *bc->bufp = solv_free(*bc->bufp); cookie_bufclose(bc); } return fp; }
Chksum * solv_chksum_create(Id type) { Chksum *chk; chk = solv_calloc(1, sizeof(*chk)); chk->type = type; switch(type) { case REPOKEY_TYPE_MD5: solv_MD5_Init(&chk->c.md5); return chk; case REPOKEY_TYPE_SHA1: solv_SHA1_Init(&chk->c.sha1); return chk; case REPOKEY_TYPE_SHA224: solv_SHA224_Init(&chk->c.sha224); return chk; case REPOKEY_TYPE_SHA256: solv_SHA256_Init(&chk->c.sha256); return chk; case REPOKEY_TYPE_SHA384: solv_SHA384_Init(&chk->c.sha384); return chk; case REPOKEY_TYPE_SHA512: solv_SHA512_Init(&chk->c.sha512); return chk; default: break; } free(chk); return 0; }
static struct Solutions * solutions_create(void) { struct Solutions *solutions = solv_calloc(1, sizeof(struct Solutions)); solutions->installs = hy_packagelist_create(); return solutions; }
static Hashtable growhash(Hashtable map, Hashval *mapnp) { Hashval mapn = *mapnp; Hashval newn = (mapn + 1) * 2 - 1; Hashval i, h, hh; Hashtable m; Id hx, qx; m = solv_calloc(newn + 1, 2 * sizeof(Id)); for (i = 0; i <= mapn; i++) { hx = map[2 * i]; if (!hx) continue; h = hx & newn; hh = HASHCHAIN_START; for (;;) { qx = m[2 * h]; if (!qx) break; h = HASHCHAIN_NEXT(h, hh, newn); } m[2 * h] = hx; m[2 * h + 1] = map[2 * i + 1]; } solv_free(map); *mapnp = newn; return m; }
HyReldep reldep_create(Pool *pool, Id r_id) { HyReldep reldep = solv_calloc(1, sizeof(*reldep)); reldep->pool = pool; reldep->r_id = r_id; return reldep; }
HyReldepList reldeplist_from_queue(Pool *pool, Queue h) { HyReldepList reldeplist = solv_calloc(1, sizeof(*reldeplist)); reldeplist->pool = pool; queue_init_clone(&reldeplist->queue, &h); return reldeplist; }
HyAdvisoryList advisorylist_create(Pool *pool) { HyAdvisoryList advisorylist = solv_calloc(1, sizeof(*advisorylist)); advisorylist->pool = pool; queue_init(&advisorylist->queue); return advisorylist; }
HyAdvisory advisory_create(Pool *pool, Id a_id) { HyAdvisory advisory = solv_calloc(1, sizeof(*advisory)); advisory->pool = pool; advisory->a_id = a_id; return advisory; }
HyReldepList hy_reldeplist_create(HySack sack) { HyReldepList reldeplist = solv_calloc(1, sizeof(*reldeplist)); reldeplist->pool = sack_pool(sack); queue_init(&reldeplist->queue); return reldeplist; }
HyRepo hy_repo_create(const char *name) { assert(name); HyRepo repo = solv_calloc(1, sizeof(*repo)); repo->nrefs = 1; hy_repo_set_string(repo, HY_REPO_NAME, name); return repo; }
HyPackage package_create(HySack sack, Id id) { HyPackage pkg; pkg = solv_calloc(1, sizeof(*pkg)); pkg->nrefs = 1; pkg->sack = sack; pkg->id = id; return pkg; }
/* * we support three relations: * * a = b both architectures a and b are treated as equivalent * a > b a is considered a "better" architecture, the solver * should change from a to b, but must not change from b to a * a : b a is considered a "better" architecture, the solver * must not change the architecture from a to b or b to a */ void pool_setarchpolicy(Pool *pool, const char *arch) { unsigned int score = 0x10001; size_t l; char d; Id *id2arch; Id id, lastarch; pool->id2arch = solv_free(pool->id2arch); pool->id2color = solv_free(pool->id2color); if (!arch) { pool->lastarch = 0; return; } id = pool->noarchid; lastarch = id + 255; /* note that we overallocate one element to be compatible with * old versions that accessed id2arch[lastarch]. * id2arch[lastarch] will always be zero */ id2arch = solv_calloc(lastarch + 1, sizeof(Id)); id2arch[id] = 1; /* the "noarch" class */ d = 0; while (*arch) { l = strcspn(arch, ":=>"); if (l) { id = pool_strn2id(pool, arch, l, 1); if (id >= lastarch) { id2arch = solv_realloc2(id2arch, (id + 255 + 1), sizeof(Id)); memset(id2arch + lastarch + 1, 0, (id + 255 - lastarch) * sizeof(Id)); lastarch = id + 255; } if (id2arch[id] == 0) { if (d == ':') score += 0x10000; else if (d == '>') score += 0x00001; id2arch[id] = score; } } arch += l; if ((d = *arch++) == 0) break; } pool->id2arch = id2arch; pool->lastarch = lastarch; }
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; }
/* * we support three relations: * * a = b both architectures a and b are treated as equivalent * a > b a is considered a "better" architecture, the solver * should change from a to b, but must not change from b to a * a : b a is considered a "better" architecture, the solver * must not change the architecture from a to b or b to a */ void pool_setarchpolicy(Pool *pool, const char *arch) { unsigned int score = 0x10001; size_t l; char d; Id *id2arch; Id id, lastarch; pool->id2arch = solv_free(pool->id2arch); pool->id2color = solv_free(pool->id2color); if (!arch) { pool->lastarch = 0; return; } id = pool->noarchid; lastarch = id + 255; id2arch = solv_calloc(lastarch + 1, sizeof(Id)); id2arch[id] = 1; /* the "noarch" class */ d = 0; while (*arch) { l = strcspn(arch, ":=>"); if (l) { id = pool_strn2id(pool, arch, l, 1); if (id > lastarch) { id2arch = solv_realloc2(id2arch, (id + 255 + 1), sizeof(Id)); memset(id2arch + lastarch + 1, 0, (id + 255 - lastarch) * sizeof(Id)); lastarch = id + 255; } if (id2arch[id] == 0) { if (d == ':') score += 0x10000; else if (d == '>') score += 0x00001; id2arch[id] = score; } } arch += l; if ((d = *arch++) == 0) break; } pool->id2arch = id2arch; pool->lastarch = lastarch; }
Repo * repo_create(Pool *pool, const char *name) { Repo *repo; pool_freewhatprovides(pool); repo = (Repo *)solv_calloc(1, sizeof(*repo)); if (!pool->nrepos) { pool->nrepos = 1; /* start with repoid 1 */ pool->repos = (Repo **)solv_calloc(2, sizeof(Repo *)); } else pool->repos = (Repo **)solv_realloc2(pool->repos, pool->nrepos + 1, sizeof(Repo *)); pool->repos[pool->nrepos] = repo; pool->urepos++; repo->repoid = pool->nrepos++; repo->name = name ? solv_strdup(name) : 0; repo->pool = pool; repo->start = pool->nsolvables; repo->end = pool->nsolvables; repo->nsolvables = 0; return repo; }
static Hashtable joinhash_init(Repo *repo, Hashval *hmp) { Hashval hm = mkmask(repo->nsolvables); Hashtable ht = solv_calloc(hm + 1, sizeof(*ht)); Hashval h, hh; Solvable *s; int i; FOR_REPO_SOLVABLES(repo, i, s) { hh = HASHCHAIN_START; h = s->name & hm; while (ht[h]) h = HASHCHAIN_NEXT(h, hh, hm); ht[h] = i; }
unsigned char pool_arch2color_slow(Pool *pool, Id arch) { const char *s; unsigned char color; if (arch > pool->lastarch) return ARCHCOLOR_ALL; if (!pool->id2color) pool->id2color = solv_calloc(pool->lastarch + 1, 1); s = pool_id2str(pool, arch); if (arch == ARCH_NOARCH || arch == ARCH_ALL || arch == ARCH_ANY) color = ARCHCOLOR_ALL; else if (!strcmp(s, "s390x") || strstr(s, "64")) color = ARCHCOLOR_64; else color = ARCHCOLOR_32; pool->id2color[arch] = color; return color; }
void * solv_chksum_create(Id type) { struct ctxhandle *h; h = solv_calloc(1, sizeof(*h)); h->type = type; switch(type) { case REPOKEY_TYPE_MD5: solv_MD5_Init(&h->c.md5); return h; case REPOKEY_TYPE_SHA1: solv_SHA1_Init(&h->c.sha1); return h; case REPOKEY_TYPE_SHA256: solv_SHA256_Init(&h->c.sha256); return h; default: break; } free(h); return 0; }
void pool_setvendorclasses(Pool *pool, const char **vendorclasses) { int i; const char **v; if (pool->vendorclasses) { for (v = pool->vendorclasses; v[0] || v[1]; v++) solv_free((void *)*v); pool->vendorclasses = solv_free((void *)pool->vendorclasses); } if (!vendorclasses || !vendorclasses[0]) return; for (v = vendorclasses; v[0] || v[1]; v++) ; pool->vendorclasses = solv_calloc(v - vendorclasses + 2, sizeof(const char *)); for (v = vendorclasses, i = 0; v[0] || v[1]; v++, i++) pool->vendorclasses[i] = *v ? solv_strdup(*v) : 0; pool->vendorclasses[i++] = 0; pool->vendorclasses[i] = 0; queue_empty(&pool->vendormap); }
void sack_recompute_considered(HySack sack) { Pool *pool = sack_pool(sack); if (sack->considered_uptodate) return; if (!pool->considered) { if (!sack->repo_excludes && !sack->pkg_excludes) return; pool->considered = solv_calloc(1, sizeof(Map)); map_init(pool->considered, pool->nsolvables); } else map_grow(pool->considered, pool->nsolvables); // considered = (all - repo_excludes - pkg_excludes) and pkg_includes map_setall(pool->considered); if (sack->repo_excludes) map_subtract(pool->considered, sack->repo_excludes); if (sack->pkg_excludes) map_subtract(pool->considered, sack->pkg_excludes); if (sack->pkg_includes) map_and(pool->considered, sack->pkg_includes); sack->considered_uptodate = 1; }
* bitmap.c * */ #include <stdlib.h> #include <string.h> #include "bitmap.h" #include "util.h" /* constructor */ void map_init(Map *m, int n) { m->size = (n + 7) >> 3; m->map = m->size ? solv_calloc(m->size, 1) : 0; } /* destructor */ void map_free(Map *m) { m->map = solv_free(m->map); m->size = 0; } /* copy constructor t <- s */ void map_init_clone(Map *t, Map *s) { t->size = s->size;
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); }
int pool_findfileconflicts(Pool *pool, Queue *pkgs, int cutoff, Queue *conflicts, int flags, void *(*handle_cb)(Pool *, Id, void *) , void *handle_cbdata) { int i, j, cflmapn, idxmapset; struct cbdata cbdata; unsigned int now, start; void *handle; Repo *installed = pool->installed; Id p; int obsoleteusescolors = pool_get_flag(pool, POOL_FLAG_OBSOLETEUSESCOLORS); int hdrfetches; queue_empty(conflicts); if (!pkgs->count) return 0; now = start = solv_timems(0); POOL_DEBUG(SOLV_DEBUG_STATS, "searching for file conflicts\n"); POOL_DEBUG(SOLV_DEBUG_STATS, "packages: %d, cutoff %d\n", pkgs->count, cutoff); memset(&cbdata, 0, sizeof(cbdata)); cbdata.aliases = flags & FINDFILECONFLICTS_CHECK_DIRALIASING; cbdata.pool = pool; if (cbdata.aliases && (flags & FINDFILECONFLICTS_USE_ROOTDIR) != 0) { cbdata.rootdir = pool_get_rootdir(pool); if (cbdata.rootdir && !strcmp(cbdata.rootdir, "/")) cbdata.rootdir = 0; if (cbdata.rootdir) cbdata.rootdirl = strlen(cbdata.rootdir); if (!cbdata.rootdir) cbdata.usestat = 1; } queue_init(&cbdata.lookat); queue_init(&cbdata.lookat_dir); map_init(&cbdata.idxmap, pkgs->count); if (cutoff <= 0) cutoff = pkgs->count; /* avarage file list size: 200 files per package */ /* avarage dir count: 20 dirs per package */ /* first pass: scan dirs */ if (!cbdata.aliases) { hdrfetches = 0; cflmapn = (cutoff + 3) * 64; while ((cflmapn & (cflmapn - 1)) != 0) cflmapn = cflmapn & (cflmapn - 1); cbdata.dirmap = solv_calloc(cflmapn, 2 * sizeof(Id)); cbdata.dirmapn = cflmapn - 1; /* make it a mask */ cbdata.create = 1; idxmapset = 0; for (i = 0; i < pkgs->count; i++) { if (i == cutoff) cbdata.create = 0; cbdata.idx = i; p = pkgs->elements[i]; if ((flags & FINDFILECONFLICTS_USE_SOLVABLEFILELIST) != 0 && installed) { if (p >= installed->start && p < installed->end && pool->solvables[p].repo == installed) { iterate_solvable_dirs(pool, p, finddirs_cb, &cbdata); if (MAPTST(&cbdata.idxmap, i)) idxmapset++; continue; } } handle = (*handle_cb)(pool, p, handle_cbdata); if (!handle) continue; hdrfetches++; rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_ONLYDIRS, finddirs_cb, &cbdata); if (MAPTST(&cbdata.idxmap, i)) idxmapset++; } POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap size: %d, used %d\n", cbdata.dirmapn + 1, cbdata.dirmapused); POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap memory usage: %d K\n", (cbdata.dirmapn + 1) * 2 * (int)sizeof(Id) / 1024); POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches); POOL_DEBUG(SOLV_DEBUG_STATS, "dirmap creation took %d ms\n", solv_timems(now)); POOL_DEBUG(SOLV_DEBUG_STATS, "dir conflicts found: %d, idxmap %d of %d\n", cbdata.dirconflicts, idxmapset, pkgs->count); } /* second pass: scan files */ now = solv_timems(0); cflmapn = (cutoff + 3) * 128; while ((cflmapn & (cflmapn - 1)) != 0) cflmapn = cflmapn & (cflmapn - 1); cbdata.cflmap = solv_calloc(cflmapn, 2 * sizeof(Id)); cbdata.cflmapn = cflmapn - 1; /* make it a mask */ cbdata.create = 1; hdrfetches = 0; for (i = 0; i < pkgs->count; i++) { if (i == cutoff) cbdata.create = 0; if (!cbdata.aliases && !MAPTST(&cbdata.idxmap, i)) continue; cbdata.idx = i; p = pkgs->elements[i]; if (!cbdata.create && (flags & FINDFILECONFLICTS_USE_SOLVABLEFILELIST) != 0 && installed) { if (p >= installed->start && p < installed->end && pool->solvables[p].repo == installed) if (!precheck_solvable_files(&cbdata, pool, p)) continue; } /* can't use FINDFILECONFLICTS_USE_SOLVABLEFILELIST because we have to know if * the file is a directory or not */ handle = (*handle_cb)(pool, p, handle_cbdata); if (!handle) continue; hdrfetches++; cbdata.lastdiridx = -1; rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, cbdata.aliases ? findfileconflicts_basename_cb : findfileconflicts_cb, &cbdata); } POOL_DEBUG(SOLV_DEBUG_STATS, "filemap size: %d, used %d\n", cbdata.cflmapn + 1, cbdata.cflmapused); POOL_DEBUG(SOLV_DEBUG_STATS, "filemap memory usage: %d K\n", (cbdata.cflmapn + 1) * 2 * (int)sizeof(Id) / 1024); POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches); POOL_DEBUG(SOLV_DEBUG_STATS, "filemap creation took %d ms\n", solv_timems(now)); POOL_DEBUG(SOLV_DEBUG_STATS, "lookat_dir size: %d\n", cbdata.lookat_dir.count); queue_free(&cbdata.lookat_dir); /* we need another pass for aliases */ if (cbdata.aliases) { now = solv_timems(0); /* make sure the first offset is not zero */ addfilesspace(&cbdata, 1); cflmapn = (cutoff + 3) * 16; while ((cflmapn & (cflmapn - 1)) != 0) cflmapn = cflmapn & (cflmapn - 1); cbdata.normap = solv_calloc(cflmapn, 2 * sizeof(Id)); cbdata.normapn = cflmapn - 1; /* make it a mask */ if (cbdata.usestat) { cbdata.statmap = solv_calloc(cflmapn, 2 * sizeof(Id)); cbdata.statmapn = cflmapn - 1; /* make it a mask */ } cbdata.create = 0; hdrfetches = 0; for (i = 0; i < pkgs->count; i++) { if (!MAPTST(&cbdata.idxmap, i)) continue; p = pkgs->elements[i]; cbdata.idx = i; /* can't use FINDFILECONFLICTS_USE_SOLVABLEFILELIST because we have to know if * the file is a directory or not */ handle = (*handle_cb)(pool, p, handle_cbdata); if (!handle) continue; hdrfetches++; cbdata.lastdiridx = -1; rpm_iterate_filelist(handle, RPM_ITERATE_FILELIST_NOGHOSTS, findfileconflicts_alias_cb, &cbdata); } POOL_DEBUG(SOLV_DEBUG_STATS, "normap size: %d, used %d\n", cbdata.normapn + 1, cbdata.normapused); POOL_DEBUG(SOLV_DEBUG_STATS, "normap memory usage: %d K\n", (cbdata.normapn + 1) * 2 * (int)sizeof(Id) / 1024); POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches); POOL_DEBUG(SOLV_DEBUG_STATS, "stats made: %d\n", cbdata.statsmade); if (cbdata.usestat) { POOL_DEBUG(SOLV_DEBUG_STATS, "statmap size: %d, used %d\n", cbdata.statmapn + 1, cbdata.statmapused); POOL_DEBUG(SOLV_DEBUG_STATS, "statmap memory usage: %d K\n", (cbdata.statmapn + 1) * 2 * (int)sizeof(Id) / 1024); } cbdata.statmap = solv_free(cbdata.statmap); cbdata.statmapn = 0; cbdata.canonspace = solv_free(cbdata.canonspace); cbdata.canonspacen = 0; POOL_DEBUG(SOLV_DEBUG_STATS, "alias processing took %d ms\n", solv_timems(now)); } cbdata.dirmap = solv_free(cbdata.dirmap); cbdata.dirmapn = 0; cbdata.dirmapused = 0; cbdata.cflmap = solv_free(cbdata.cflmap); cbdata.cflmapn = 0; cbdata.cflmapused = 0; map_free(&cbdata.idxmap); /* sort and unify/prune */ now = solv_timems(0); POOL_DEBUG(SOLV_DEBUG_STATS, "raw candidates: %d, pruning\n", cbdata.lookat.count / 4); solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_hx_cmp, pool); for (i = j = 0; i < cbdata.lookat.count; ) { int first = 1; Id hx = cbdata.lookat.elements[i]; Id idx = cbdata.lookat.elements[i + 1]; Id dhx = cbdata.lookat.elements[i + 2]; Id dirid = cbdata.lookat.elements[i + 3]; i += 4; for (; i < cbdata.lookat.count && hx == cbdata.lookat.elements[i] && (dirid == cbdata.lookat.elements[i + 3] || dirid == -cbdata.lookat.elements[i + 3]); i += 4) { if (idx == cbdata.lookat.elements[i + 1] && dhx == cbdata.lookat.elements[i + 2]) continue; /* ignore duplicates */ if (first) { if (dirid < 0) continue; /* all have a neg dirid */ cbdata.lookat.elements[j++] = hx; cbdata.lookat.elements[j++] = idx; cbdata.lookat.elements[j++] = dhx; cbdata.lookat.elements[j++] = dirid; first = 0; } idx = cbdata.lookat.elements[i + 1]; dhx = cbdata.lookat.elements[i + 2]; cbdata.lookat.elements[j++] = hx; cbdata.lookat.elements[j++] = idx; cbdata.lookat.elements[j++] = dhx; cbdata.lookat.elements[j++] = dirid; } } queue_truncate(&cbdata.lookat, j); POOL_DEBUG(SOLV_DEBUG_STATS, "candidates now: %d\n", cbdata.lookat.count / 4); POOL_DEBUG(SOLV_DEBUG_STATS, "pruning took %d ms\n", solv_timems(now)); /* third pass: collect file info for all files that match a hx */ now = solv_timems(0); solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_idx_cmp, pool); queue_init(&cbdata.files); hdrfetches = 0; for (i = 0; i < cbdata.lookat.count; i += 4) { Id idx = cbdata.lookat.elements[i + 1]; int iterflags = RPM_ITERATE_FILELIST_WITHMD5 | RPM_ITERATE_FILELIST_NOGHOSTS; if (obsoleteusescolors) iterflags |= RPM_ITERATE_FILELIST_WITHCOL; p = pkgs->elements[idx]; handle = (*handle_cb)(pool, p, handle_cbdata); if (handle) hdrfetches++; for (;; i += 4) { int fstart = cbdata.files.count; queue_push(&cbdata.files, idx); queue_push(&cbdata.files, 0); cbdata.idx = idx; cbdata.hx = cbdata.lookat.elements[i]; cbdata.dirhash = cbdata.lookat.elements[i + 2]; cbdata.dirid = cbdata.lookat.elements[i + 3]; cbdata.lastdiridx = -1; if (handle) rpm_iterate_filelist(handle, iterflags, findfileconflicts2_cb, &cbdata); cbdata.files.elements[fstart + 1] = cbdata.files.count; cbdata.lookat.elements[i + 1] = fstart; if (i + 4 >= cbdata.lookat.count || cbdata.lookat.elements[i + 4 + 1] != idx) break; } } POOL_DEBUG(SOLV_DEBUG_STATS, "header fetches: %d\n", hdrfetches); POOL_DEBUG(SOLV_DEBUG_STATS, "file info fetching took %d ms\n", solv_timems(now)); cbdata.normap = solv_free(cbdata.normap); cbdata.normapn = 0; /* forth pass: for each hx we have, compare all matching files against all other matching files */ now = solv_timems(0); solv_sort(cbdata.lookat.elements, cbdata.lookat.count / 4, sizeof(Id) * 4, &lookat_hx_cmp, pool); for (i = 0; i < cbdata.lookat.count - 4; i += 4) { Id hx = cbdata.lookat.elements[i]; Id pstart = cbdata.lookat.elements[i + 1]; Id dirid = cbdata.lookat.elements[i + 3]; Id pidx = cbdata.files.elements[pstart]; Id pend = cbdata.files.elements[pstart + 1]; if (cbdata.lookat.elements[i + 4] != hx) continue; /* no package left with that hx */ for (j = i + 4; j < cbdata.lookat.count && cbdata.lookat.elements[j] == hx && cbdata.lookat.elements[j + 3] == dirid; j += 4) { Id qstart = cbdata.lookat.elements[j + 1]; Id qidx = cbdata.files.elements[qstart]; Id qend = cbdata.files.elements[qstart + 1]; int ii, jj; if (pidx >= cutoff && qidx >= cutoff) continue; /* no conflicts between packages with idx >= cutoff */ for (ii = pstart + 2; ii < pend; ii++) for (jj = qstart + 2; jj < qend; jj++) { char *fsi = (char *)cbdata.filesspace + cbdata.files.elements[ii]; char *fsj = (char *)cbdata.filesspace + cbdata.files.elements[jj]; if (cbdata.aliases) { /* compare just the basenames, the dirs match because of the dirid */ char *bsi = strrchr(fsi + 34, '/'); char *bsj = strrchr(fsj + 34, '/'); if (!bsi || !bsj) continue; if (strcmp(bsi, bsj)) continue; /* different base names */ } else { if (strcmp(fsi + 34, fsj + 34)) continue; /* different file names */ } if (!strcmp(fsi, fsj)) continue; /* file digests match, no conflict */ if (obsoleteusescolors && fsi[33] && fsj[33] && (fsi[33] & fsj[33]) == 0) continue; /* colors do not conflict */ queue_push(conflicts, pool_str2id(pool, fsi + 34, 1)); queue_push(conflicts, pkgs->elements[pidx]); queue_push(conflicts, pool_str2id(pool, fsi, 1)); queue_push(conflicts, pool_str2id(pool, fsj + 34, 1)); queue_push(conflicts, pkgs->elements[qidx]); queue_push(conflicts, pool_str2id(pool, fsj, 1)); } } } POOL_DEBUG(SOLV_DEBUG_STATS, "filespace size: %d K\n", cbdata.filesspacen / 1024); POOL_DEBUG(SOLV_DEBUG_STATS, "candidate check took %d ms\n", solv_timems(now)); cbdata.filesspace = solv_free(cbdata.filesspace); cbdata.filesspacen = 0; queue_free(&cbdata.lookat); queue_free(&cbdata.files); if (conflicts->count > 6) solv_sort(conflicts->elements, conflicts->count / 6, 6 * sizeof(Id), conflicts_cmp, pool); POOL_DEBUG(SOLV_DEBUG_STATS, "found %d file conflicts\n", conflicts->count / 6); POOL_DEBUG(SOLV_DEBUG_STATS, "file conflict detection took %d ms\n", solv_timems(start)); return conflicts->count / 6; }
struct solv_zchunk * solv_zchunk_open(FILE *fp, unsigned int streamid) { struct solv_zchunk *zck; unsigned char *p; unsigned int hdr_size; /* preface + index + signatures */ unsigned int lead_size; unsigned int preface_size; unsigned int index_size; zck = solv_calloc(1, sizeof(*zck)); /* read and parse the lead, read the complete header */ zck->hdr = solv_calloc(15, 1); zck->hdr_end = zck->hdr + 15; if (fread(zck->hdr, 15, 1, fp) != 1 || memcmp(zck->hdr, "\000ZCK1", 5) != 0) return open_error(zck); p = zck->hdr + 5; if ((p = getchksum(p, zck->hdr_end, &zck->hdr_chk_type, &zck->hdr_chk_len, &zck->hdr_chk_id)) == 0) return open_error(zck); if ((p = getuint(p, zck->hdr_end, &hdr_size)) == 0 || hdr_size > MAX_HDR_SIZE) return open_error(zck); lead_size = p - zck->hdr + zck->hdr_chk_len; zck->hdr = solv_realloc(zck->hdr, lead_size + hdr_size); zck->hdr_end = zck->hdr + lead_size + hdr_size; if (fread(zck->hdr + 15, lead_size + hdr_size - 15, 1, fp) != 1) return open_error(zck); /* verify header checksum to guard against corrupt files */ if (zck->hdr_chk_id) { Chksum *chk = solv_chksum_create(zck->hdr_chk_id); if (!chk) return open_error(zck); solv_chksum_add(chk, zck->hdr, lead_size - zck->hdr_chk_len); solv_chksum_add(chk, zck->hdr + lead_size, hdr_size); if (memcmp(solv_chksum_get(chk, 0), zck->hdr + (lead_size - zck->hdr_chk_len), zck->hdr_chk_len) != 0) { solv_chksum_free(chk, 0); return open_error(zck); } solv_chksum_free(chk, 0); } /* parse preface: data chksum, flags, compression */ p = zck->hdr + lead_size; if (p + zck->hdr_chk_len > zck->hdr_end) return open_error(zck); zck->data_chk_ptr = p; p += zck->hdr_chk_len; #ifdef VERIFY_DATA_CHKSUM if (zck->hdr_chk_id && (zck->data_chk = solv_chksum_create(zck->hdr_chk_id)) == 0) return open_error(zck); #endif if ((p = getuint(p, zck->hdr_end, &zck->flags)) == 0) return open_error(zck); if ((zck->flags & ~(3)) != 0) return open_error(zck); if ((p = getuint(p, zck->hdr_end, &zck->comp)) == 0 || (zck->comp != 0 && zck->comp != 2)) return open_error(zck); /* only uncompressed + zstd supported */ /* skip all optional elements if present */ if ((zck->flags & 2) != 0) { unsigned int nopt, lopt; if ((p = getuint(p, zck->hdr_end, &nopt)) == 0) return open_error(zck); for (; nopt != 0; nopt--) { if ((p = getuint(p, zck->hdr_end, &lopt)) == 0) return open_error(zck); if ((p = getuint(p, zck->hdr_end, &lopt)) == 0) return open_error(zck); if (p + lopt > zck->hdr_end) return open_error(zck); p += lopt; } } preface_size = p - (zck->hdr + lead_size); /* parse index: index size, index chksum type, num chunks, chunk data */ if ((p = getuint(p, zck->hdr_end, &index_size)) == 0) return open_error(zck); if (hdr_size < preface_size + index_size) return open_error(zck); if ((p = getchksum(p, zck->hdr_end, &zck->chunk_chk_type, &zck->chunk_chk_len, &zck->chunk_chk_id)) == 0) return open_error(zck); if ((p = getuint(p, zck->hdr_end, &zck->nchunks)) == 0 || zck->nchunks > MAX_CHUNK_CNT) return open_error(zck); /* setup decompressor */ if (zck->comp == 2) { if ((zck->dctx = ZSTD_createDCtx()) == 0) return open_error(zck); } zck->fp = fp; zck->chunks = p; zck->streamid = streamid; if (streamid == 0) { zck->nchunks = zck->nchunks ? 1 : 0; /* limit to dict chunk */ return zck; } /* setup dictionary */ if (!nextchunk(zck, 0)) { zck->fp = 0; return open_error(zck); } if (zck->comp == 2 && zck->buf_avail) { if ((zck->ddict = ZSTD_createDDict(zck->buf, zck->buf_avail)) == 0) { zck->fp = 0; return open_error(zck); } } zck->buf = solv_free(zck->buf); zck->buf_used = 0; zck->buf_avail = 0; /* ready to read the rest of the chunks */ return zck; }
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; }
HyPackageList hy_packagelist_create(void) { HyPackageList plist = solv_calloc(1, sizeof(*plist)); return plist; }
HyPackageDelta delta_create(void) { HyPackageDelta delta = solv_calloc(1, sizeof(*delta)); return delta; }
Id pool_rel2id(Pool *pool, Id name, Id evr, int flags, int create) { Hashval h, hh, hashmask; int i; Id id; Hashtable hashtbl; Reldep *ran; hashmask = pool->relhashmask; hashtbl = pool->relhashtbl; ran = pool->rels; /* extend hashtable if needed */ if (pool->nrels * 2 > hashmask) { solv_free(pool->relhashtbl); pool->relhashmask = hashmask = mkmask(pool->nrels + REL_BLOCK); pool->relhashtbl = hashtbl = solv_calloc(hashmask + 1, sizeof(Id)); /* rehash all rels into new hashtable */ for (i = 1; i < pool->nrels; i++) { h = relhash(ran[i].name, ran[i].evr, ran[i].flags) & hashmask; hh = HASHCHAIN_START; while (hashtbl[h]) h = HASHCHAIN_NEXT(h, hh, hashmask); hashtbl[h] = i; } } /* compute hash and check for match */ h = relhash(name, evr, flags) & hashmask; hh = HASHCHAIN_START; while ((id = hashtbl[h]) != 0) { if (ran[id].name == name && ran[id].evr == evr && ran[id].flags == flags) break; h = HASHCHAIN_NEXT(h, hh, hashmask); } if (id) return MAKERELDEP(id); if (!create) return ID_NULL; id = pool->nrels++; /* extend rel space if needed */ pool->rels = solv_extend(pool->rels, id, 1, sizeof(Reldep), REL_BLOCK); hashtbl[h] = id; ran = pool->rels + id; ran->name = name; ran->evr = evr; ran->flags = flags; /* extend whatprovides_rel if needed */ if (pool->whatprovides_rel && (id & WHATPROVIDES_BLOCK) == 0) { pool->whatprovides_rel = solv_realloc2(pool->whatprovides_rel, id + (WHATPROVIDES_BLOCK + 1), sizeof(Offset)); memset(pool->whatprovides_rel + id, 0, (WHATPROVIDES_BLOCK + 1) * sizeof(Offset)); } return MAKERELDEP(id); }