/* remove all references from a given identifier */ retvalue references_remove(const char *neededby) { struct cursor *cursor; retvalue result, r; const char *found_to, *found_by; size_t datalen, l; r = table_newglobalcursor(rdb_references, &cursor); if (!RET_IS_OK(r)) return r; l = strlen(neededby); result = RET_NOTHING; while (cursor_nexttempdata(rdb_references, cursor, &found_to, &found_by, &datalen)) { if (datalen >= l && strncmp(found_by, neededby, l) == 0 && (found_by[l] == '\0' || found_by[l] == ' ')) { if (verbose > 8) fprintf(stderr, "Removing reference to '%s' by '%s'\n", found_to, neededby); r = cursor_delete(rdb_references, cursor, found_to, NULL); RET_UPDATE(result, r); if (RET_IS_OK(r)) { r = pool_dereferenced(found_to); RET_ENDUPDATE(result, r); } } } r = cursor_close(rdb_references, cursor); RET_ENDUPDATE(result, r); return result; }
/* dump all references to stdout */ retvalue references_dump(void) { struct cursor *cursor; retvalue result, r; const char *found_to, *found_by; r = table_newglobalcursor(rdb_references, &cursor); if (!RET_IS_OK(r)) return r; result = RET_OK; while (cursor_nexttemp(rdb_references, cursor, &found_to, &found_by)) { if (fputs(found_by, stdout) == EOF || putchar(' ') == EOF || puts(found_to) == EOF) { result = RET_ERROR; break; } result = RET_OK; if (interrupted()) { result = RET_ERROR_INTERRUPTED; break; } } r = cursor_close(rdb_references, cursor); RET_ENDUPDATE(result, r); return result; }
/* dump out all information */ retvalue files_printmd5sums(void) { retvalue result, r; struct cursor *cursor; const char *filekey, *checksum; r = table_newglobalcursor(rdb_checksums, &cursor); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; while (cursor_nexttemp(rdb_checksums, cursor, &filekey, &checksum)) { result = RET_OK; (void)fputs(filekey, stdout); (void)putchar(' '); while (*checksum == ':') { while (*checksum != ' ' && *checksum != '\0') checksum++; if (*checksum == ' ') checksum++; } (void)fputs(checksum, stdout); (void)putchar('\n'); } r = cursor_close(rdb_checksums, cursor); RET_ENDUPDATE(result, r); return result; }
retvalue tracking_printall(trackingdb t) { struct cursor *cursor; retvalue result, r; struct trackedpackage *pkg; const char *key, *value, *data; size_t datalen; r = table_newglobalcursor(t->table, &cursor); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; while (cursor_nextpair(t->table, cursor, &key, &value, &data, &datalen)) { r = parse_data(key, value, data, datalen, &pkg); if (RET_IS_OK(r)) { print(t->codename, pkg); trackedpackage_free(pkg); } RET_UPDATE(result, r); } r = cursor_close(t->table, cursor); RET_ENDUPDATE(result, r); return result; }
retvalue tracking_removepackages(trackingdb t, struct distribution *distribution, const char *sourcename, /*@null@*/const char *version) { struct trackedpackage *pkg; retvalue result, r; if (version == NULL) return tracking_foreachversion(t, distribution, sourcename, removesourcepackage); result = tracking_get(t, sourcename, version, &pkg); if (RET_IS_OK(result)) { result = removesourcepackage(t, pkg, distribution); if (RET_IS_OK(result)) { r = trackedpackage_tidy(t, pkg); RET_ENDUPDATE(result, r); r = tracking_save(t, pkg); RET_ENDUPDATE(result, r); } else trackedpackage_free(pkg); } return result; }
/* Try to remove all packages causing refcounts in this tracking record */ static retvalue removesourcepackage(trackingdb t, struct trackedpackage *pkg, struct distribution *distribution) { struct target *target; retvalue result, r; int i; result = RET_NOTHING; for (target = distribution->targets ; target != NULL ; target = target->next) { r = target_initpackagesdb(target, READWRITE); RET_ENDUPDATE(result, r); if (RET_IS_OK(r)) { r = targetremovesourcepackage(t, pkg, distribution, target); RET_UPDATE(result, r); RET_UPDATE(distribution->status, r); r = target_closepackagesdb(target); RET_ENDUPDATE(result, r); RET_ENDUPDATE(distribution->status, r); if (RET_WAS_ERROR(result)) return result; } } for (i = 0 ; i < pkg->filekeys.count ; i++) { const char *filekey = pkg->filekeys.values[i]; if (pkg->refcounts[i] <= 0) continue; if (pkg->filetypes[i] != ft_ALL_BINARY && pkg->filetypes[i] != ft_SOURCE && pkg->filetypes[i] != ft_ARCH_BINARY) continue; fprintf(stderr, "There was an inconsistency in the tracking data of '%s':\n" "'%s' has refcount > 0, but was nowhere found.\n", distribution->codename, filekey); pkg->refcounts[i] = 0; } return result; }
retvalue files_collectnewchecksums(void) { retvalue result, r; struct cursor *cursor; const char *filekey, *all; size_t alllen; struct checksums *expected; char *fullfilename; result = RET_NOTHING; r = table_newglobalcursor(rdb_checksums, &cursor); if (!RET_IS_OK(r)) return r; while (cursor_nexttempdata(rdb_checksums, cursor, &filekey, &all, &alllen)) { r = checksums_setall(&expected, all, alllen); if (!RET_IS_OK(r)) { RET_UPDATE(result, r); continue; } if (checksums_iscomplete(expected)) { checksums_free(expected); continue; } fullfilename = files_calcfullfilename(filekey); if (FAILEDTOALLOC(fullfilename)) { result = RET_ERROR_OOM; checksums_free(expected); break; } r = checksums_complete(&expected, fullfilename); if (r == RET_NOTHING) { fprintf(stderr, "Missing file '%s'!\n", fullfilename); r = RET_ERROR_MISSING; } if (r == RET_ERROR_WRONG_MD5) { fprintf(stderr, "ERROR: Cannot collect missing checksums for '%s'\n" "as the file in the pool does not match the already recorded checksums\n", filekey); } free(fullfilename); if (RET_IS_OK(r)) r = files_replace_checksums(filekey, expected); checksums_free(expected); RET_UPDATE(result, r); } r = cursor_close(rdb_checksums, cursor); RET_ENDUPDATE(result, r); return result; }
retvalue tracking_foreach_ro(struct distribution *d, tracking_foreach_ro_action *action) { trackingdb t; struct cursor *cursor; retvalue result, r; struct trackedpackage *pkg; const char *key, *value, *data; size_t datalen; r = tracking_initialize(&t, d, true); if (!RET_IS_OK(r)) return r; r = table_newglobalcursor(t->table, &cursor); if (!RET_IS_OK(r)) { (void)tracking_done(t); return r; } result = RET_NOTHING; while (cursor_nextpair(t->table, cursor, &key, &value, &data, &datalen)) { r = parse_data(key, value, data, datalen, &pkg); if (RET_IS_OK(r)) { r = action(d, pkg); trackedpackage_free(pkg); } RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) break; } r = cursor_close(t->table, cursor); RET_ENDUPDATE(result, r); r = tracking_done(t); RET_ENDUPDATE(result, r); return result; }
retvalue files_checkpool(bool fast) { retvalue result, r; struct cursor *cursor; const char *filekey, *combined; size_t combinedlen; struct checksums *expected; char *fullfilename; bool improveable = false; result = RET_NOTHING; r = table_newglobalcursor(rdb_checksums, &cursor); if (!RET_IS_OK(r)) return r; while (cursor_nexttempdata(rdb_checksums, cursor, &filekey, &combined, &combinedlen)) { r = checksums_setall(&expected, combined, combinedlen); if (RET_WAS_ERROR(r)) { RET_UPDATE(result, r); continue; } fullfilename = files_calcfullfilename(filekey); if (FAILEDTOALLOC(fullfilename)) { result = RET_ERROR_OOM; checksums_free(expected); break; } if (fast) r = checksums_cheaptest(fullfilename, expected, true); else r = checkpoolfile(fullfilename, expected, &improveable); if (r == RET_NOTHING) { fprintf(stderr, "Missing file '%s'!\n", fullfilename); r = RET_ERROR_MISSING; } free(fullfilename); checksums_free(expected); RET_UPDATE(result, r); } r = cursor_close(rdb_checksums, cursor); RET_ENDUPDATE(result, r); if (improveable && verbose >= 0) printf( "There were files with only some of the checksums this version of reprepro\n" "can compute recorded. To add those run reprepro collectnewchecksums.\n"); return result; }
retvalue tracking_rereference(struct distribution *distribution) { retvalue result, r; trackingdb tracks; result = references_remove(distribution->codename); if (distribution->tracking == dt_NONE) return result; r = tracking_initialize(&tracks, distribution, true); RET_UPDATE(result, r); if (!RET_IS_OK(r)) return result; r = tracking_recreatereferences(tracks); RET_UPDATE(result, r); r = tracking_done(tracks); RET_ENDUPDATE(result, r); return result; }
static retvalue tracking_saveonly(trackingdb t, struct trackedpackage *pkg) { retvalue r, r2; char *newdata; size_t newdatalen; assert (pkg != NULL); if (!pkg->flags.isnew) { struct cursor *cursor; r = table_newpairedcursor(t->table, pkg->sourcename, pkg->sourceversion, &cursor, NULL, NULL); if (RET_WAS_ERROR(r)) return r; if (r == RET_NOTHING) { fprintf(stderr, "Internal error: tracking_save with isnew=false called but could not find %s_%s in %s!\n", pkg->sourcename, pkg->sourceversion, t->codename); pkg->flags.isnew = true; } else { r = tracking_saveatcursor(t, cursor, pkg); r2 = cursor_close(t->table, cursor); RET_ENDUPDATE(r, r2); return r; } } if (pkg->flags.deleted) return RET_OK; r = gen_data(pkg, &newdata, &newdatalen); assert (r != RET_NOTHING); if (!RET_IS_OK(r)) return r; r = table_addrecord(t->table, pkg->sourcename, newdata, newdatalen, false); free(newdata); if (verbose > 18) fprintf(stderr, "Adding tracked package '%s'_'%s' to '%s'\n", pkg->sourcename, pkg->sourceversion, t->codename); return r; }
retvalue tracking_retrack(struct distribution *d, bool needsretrack) { struct target *t; trackingdb tracks; retvalue r, rr; if (d->tracking == dt_NONE) return RET_NOTHING; for (t = d->targets ; !needsretrack && t != NULL ; t = t->next) { if (t->staletracking) needsretrack = true; } if (!needsretrack) return RET_NOTHING; if (verbose > 0) printf("Retracking %s...\n", d->codename); r = tracking_initialize(&tracks, d, false); if (!RET_IS_OK(r)) return r; /* first forget that any package is there*/ r = tracking_reset(tracks); if (!RET_WAS_ERROR(r)) { /* add back information about actually used files */ r = distribution_foreach_package(d, atom_unknown, atom_unknown, atom_unknown, package_retrack, NULL, tracks); } if (RET_IS_OK(r)) { for (t = d->targets ; t != NULL ; t = t->next) { t->staletracking = false; } } if (!RET_WAS_ERROR(r)) { /* now remove everything no longer needed */ r = tracking_tidyall(tracks); } rr = tracking_done(tracks); RET_ENDUPDATE(r, rr); return r; }
retvalue tracking_remove(trackingdb t, const char *sourcename, const char *version) { retvalue result, r; struct cursor *cursor; const char *data; size_t datalen; char *id; struct trackedpackage *pkg SETBUTNOTUSED(= NULL); r = table_newpairedcursor(t->table, sourcename, version, &cursor, &data, &datalen); if (!RET_IS_OK(r)) return r; id = calc_trackreferee(t->codename, sourcename, version); if (FAILEDTOALLOC(id)) { (void)cursor_close(t->table, cursor); return RET_ERROR_OOM; } result = parse_data(sourcename, version, data, datalen, &pkg); if (RET_IS_OK(r)) { assert (pkg != NULL); r = references_delete(id, &pkg->filekeys, NULL); RET_UPDATE(result, r); trackedpackage_free(pkg); } else { RET_UPDATE(result, r); fprintf(stderr, "Could not parse data, removing all references blindly...\n"); r = references_remove(id); RET_UPDATE(result, r); } free(id); r = cursor_delete(t->table, cursor, sourcename, version); if (RET_IS_OK(r)) fprintf(stderr, "Removed %s_%s from %s.\n", sourcename, version, t->codename); RET_UPDATE(result, r); r = cursor_close(t->table, cursor); RET_ENDUPDATE(result, r); return result; }
static retvalue tracking_foreachversion(trackingdb t, struct distribution *distribution, const char *sourcename, retvalue (action)(trackingdb t, struct trackedpackage *, struct distribution *)) { struct cursor *cursor; retvalue result, r; struct trackedpackage *pkg; const char *value, *data; size_t datalen; r = table_newduplicatecursor(t->table, sourcename, &cursor, &value, &data, &datalen); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; do { r = parse_data(sourcename, value, data, datalen, &pkg); if (RET_WAS_ERROR(r)) { result = r; break; } if (verbose > 10) printf("Processing track of '%s' version '%s'\n", pkg->sourcename, pkg->sourceversion); r = action(t, pkg, distribution); RET_UPDATE(result, r); if (RET_WAS_ERROR(r)) { (void)cursor_close(t->table, cursor); trackedpackage_free(pkg); return r; } r = trackedpackage_tidy(t, pkg); RET_ENDUPDATE(result, r); r = tracking_saveatcursor(t, cursor, pkg); RET_UPDATE(result, r); trackedpackage_free(pkg); } while (cursor_nextpair(t->table, cursor, NULL, &value, &data, &datalen)); r = cursor_close(t->table, cursor); RET_UPDATE(result, r); return result; }
/* callback for each registered file */ retvalue files_foreach(per_file_action action, void *privdata) { retvalue result, r; struct cursor *cursor; const char *filekey, *checksum; r = table_newglobalcursor(rdb_checksums, &cursor); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; while (cursor_nexttemp(rdb_checksums, cursor, &filekey, &checksum)) { if (interrupted()) { RET_UPDATE(result, RET_ERROR_INTERRUPTED); break; } r = action(privdata, filekey); RET_UPDATE(result, r); } r = cursor_close(rdb_checksums, cursor); RET_ENDUPDATE(result, r); return result; }
retvalue files_printchecksums(void) { retvalue result, r; struct cursor *cursor; const char *filekey, *checksum; r = table_newglobalcursor(rdb_checksums, &cursor); if (!RET_IS_OK(r)) return r; result = RET_NOTHING; while (cursor_nexttemp(rdb_checksums, cursor, &filekey, &checksum)) { result = RET_OK; (void)fputs(filekey, stdout); (void)putchar(' '); (void)fputs(checksum, stdout); (void)putchar('\n'); if (interrupted()) { result = RET_ERROR_INTERRUPTED; break; } } r = cursor_close(rdb_checksums, cursor); RET_ENDUPDATE(result, r); return result; }
static retvalue pull_install(struct pull_distribution *distribution) { retvalue result, r; struct pull_target *u; struct distribution *d = distribution->distribution; assert (logger_isprepared(d->logger)); result = RET_NOTHING; for (u=distribution->targets ; u != NULL ; u=u->next) { r = upgradelist_install(u->upgradelist, d->logger, false, pull_from_callback); RET_UPDATE(d->status, r); RET_UPDATE(result, r); upgradelist_free(u->upgradelist); u->upgradelist = NULL; if (RET_WAS_ERROR(r)) break; } if (RET_IS_OK(result) && d->tracking != dt_NONE) { r = tracking_retrack(d, false); RET_ENDUPDATE(result, r); } return result; }