void commit_transactionelement_rpm(Pool *pool, Id type, Id p, FILE *fp) { Solvable *s = pool_id2solvable(pool, p); const char *rootdir = pool_get_rootdir(pool); const char *evr, *evrp, *nvra; switch(type) { case SOLVER_TRANSACTION_ERASE: if (!s->repo->rpmdbid || !s->repo->rpmdbid[p - s->repo->start]) break; /* strip epoch from evr */ evr = evrp = pool_id2str(pool, s->evr); while (*evrp >= '0' && *evrp <= '9') evrp++; if (evrp > evr && evrp[0] == ':' && evrp[1]) evr = evrp + 1; nvra = pool_tmpjoin(pool, pool_id2str(pool, s->name), "-", evr); nvra = pool_tmpappend(pool, nvra, ".", pool_id2str(pool, s->arch)); runrpm("-e", nvra, -1, rootdir); /* too bad that --querybynumber doesn't work */ break; case SOLVER_TRANSACTION_INSTALL: case SOLVER_TRANSACTION_MULTIINSTALL: rewind(fp); lseek(fileno(fp), 0, SEEK_SET); runrpm(type == SOLVER_TRANSACTION_MULTIINSTALL ? "-i" : "-U", "/dev/fd/3", fileno(fp), rootdir); break; default: break; } }
int repo_add_products(Repo *repo, const char *proddir, int flags) { const char *fullpath; DIR *dir; if (proddir) { dir = opendir(flags & REPO_USE_ROOTDIR ? pool_prepend_rootdir_tmp(repo->pool, proddir) : proddir); if (dir) { /* assume code11 stype products */ closedir(dir); return repo_add_code11_products(repo, proddir, flags); } } /* code11 didn't work, try old code10 zyppdb */ fullpath = "/var/lib/zypp/db/products"; if (flags & REPO_USE_ROOTDIR) fullpath = pool_prepend_rootdir_tmp(repo->pool, fullpath); dir = opendir(fullpath); if (dir) { closedir(dir); /* assume code10 style products */ return repo_add_zyppdb_products(repo, "/var/lib/zypp/db/products", flags); } /* code10/11 didn't work, try -release files parsing */ fullpath = "/etc"; if (flags & REPO_USE_ROOTDIR) fullpath = pool_prepend_rootdir_tmp(repo->pool, fullpath); dir = opendir(fullpath); if (dir) { closedir(dir); return repo_add_releasefile_products(repo, "/etc", flags); } /* no luck. check if the rootdir exists */ fullpath = pool_get_rootdir(repo->pool); if (fullpath && *fullpath) { dir = opendir(fullpath); if (!dir) return pool_error(repo->pool, -1, "%s: %s", fullpath, strerror(errno)); closedir(dir); } /* the least we can do... */ if (!(flags & REPO_NO_INTERNALIZE) && (flags & REPO_REUSE_REPODATA) != 0) repodata_internalize(repo_last_repodata(repo)); return 0; }
void commit_transactionelement_debian(Pool *pool, Id type, Id p, FILE *fp) { Solvable *s = pool_id2solvable(pool, p); const char *rootdir = pool_get_rootdir(pool); switch(type) { case SOLVER_TRANSACTION_ERASE: rundpkg("--remove", pool_id2str(pool, s->name), 0, rootdir); break; case SOLVER_TRANSACTION_INSTALL: case SOLVER_TRANSACTION_MULTIINSTALL: rewind(fp); lseek(fileno(fp), 0, SEEK_SET); rundpkg("--install", "/dev/fd/3", fileno(fp), rootdir); break; default: break; } }
int checkfileconflicts(Pool *pool, Queue *checkq, int newpkgs, FILE **newpkgsfps, Queue *conflicts) { struct fcstate fcstate; int i; printf("Searching for file conflicts\n"); queue_init(conflicts); fcstate.rpmstate = rpm_state_create(pool, pool_get_rootdir(pool)); fcstate.newpkgscnt = newpkgs; fcstate.checkq = checkq; fcstate.newpkgsfps = newpkgsfps; pool_findfileconflicts(pool, checkq, newpkgs, conflicts, FINDFILECONFLICTS_USE_SOLVABLEFILELIST | FINDFILECONFLICTS_CHECK_DIRALIASING | FINDFILECONFLICTS_USE_ROOTDIR, &fileconflict_cb, &fcstate); fcstate.rpmstate = rpm_state_free(fcstate.rpmstate); if (conflicts->count) { printf("\n"); for (i = 0; i < conflicts->count; i += 6) printf("file %s of package %s conflicts with package %s\n", pool_id2str(pool, conflicts->elements[i]), pool_solvid2str(pool, conflicts->elements[i + 1]), pool_solvid2str(pool, conflicts->elements[i + 4])); printf("\n"); } return conflicts->count; }
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; }