Beispiel #1
0
/* 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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
/* read the data from a .deb, make some checks and extract some data */
static retvalue deb_read(/*@out@*/struct debpackage **pkg, const char *filename, bool needssourceversion) {
	retvalue r;
	struct debpackage *deb;

	deb = zNEW(struct debpackage);
	if (FAILEDTOALLOC(deb))
		return RET_ERROR_OOM;

	r = binaries_readdeb(&deb->deb, filename, needssourceversion);
	if (RET_IS_OK(r))
		r = properpackagename(deb->deb.name);
	if (RET_IS_OK(r))
		r = propersourcename(deb->deb.source);
	if (RET_IS_OK(r) && needssourceversion)
		r = properversion(deb->deb.sourceversion);
	if (RET_IS_OK(r))
		r = properversion(deb->deb.version);
	if (RET_WAS_ERROR(r)) {
		deb_free(deb);
		return r;
	}
	*pkg = deb;

	return RET_OK;
}
Beispiel #4
0
retvalue getfilelist(/*@out@*/char **filelist, size_t *size, const char *debfile) {
	struct ar_archive *ar;
	retvalue r;
	bool hadcandidate = false;

	r = ar_open(&ar, debfile);
	if (RET_WAS_ERROR(r))
		return r;
	assert (r != RET_NOTHING);
	do {
		char *filename;
		enum compression c;

		r = ar_nextmember(ar, &filename);
		if (RET_IS_OK(r)) {
			if (strncmp(filename, "data.tar", 8) != 0) {
				free(filename);
				continue;
			}
			hadcandidate = true;
			for (c = 0 ; c < c_COUNT ; c++) {
				if (strcmp(filename + 8,
						uncompression_suffix[c]) == 0)
					break;
			}
			if (c >= c_COUNT) {
				free(filename);
				continue;
			}
			ar_archivemember_setcompression(ar, c);
			if (uncompression_supported(c)) {
				struct archive *tar;

				tar = archive_read_new();
				r = read_data_tar(filelist, size,
						debfile, ar, tar);
				// TODO: check how to get an error message here..
				archive_read_finish(tar);
				if (r != RET_NOTHING) {
					ar_close(ar);
					free(filename);
					return r;
				}

			}
			free(filename);
		}
	} while (RET_IS_OK(r));
	ar_close(ar);
	if (hadcandidate)
		fprintf(stderr,
"Could not find a suitable data.tar file within '%s'!\n", debfile);
	else
		fprintf(stderr,
"Could not find a data.tar file within '%s'!\n", debfile);
	return RET_ERROR_MISSING;
}
Beispiel #5
0
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;
}
Beispiel #6
0
retvalue files_add_checksums(const char *filekey, const struct checksums *checksums) {
	retvalue r;
	const char *combined;
	size_t combinedlen;

	assert (rdb_checksums != NULL);
	r = checksums_getcombined(checksums, &combined, &combinedlen);
	if (!RET_IS_OK(r))
		return r;
	r = table_adduniqsizedrecord(rdb_checksums, filekey,
			combined, combinedlen + 1, true, false);
	if (!RET_IS_OK(r))
		return r;
	return pool_markadded(filekey);
}
Beispiel #7
0
/* 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;
}
Beispiel #8
0
retvalue readtextfile(const char *source, const char *sourcetoshow, char **data, size_t *len) {
    int fd;
    char *buffer;
    size_t bufferlen;
    retvalue r;
    int ret;

    fd = open(source, O_RDONLY|O_NOCTTY);
    if (fd < 0) {
        int e = errno;
        fprintf(stderr, "Error opening '%s': %s\n",
                sourcetoshow, strerror(e));
        return RET_ERRNO(e);
    }
    r = readtextfilefd(fd, sourcetoshow, &buffer, &bufferlen);
    if (!RET_IS_OK(r)) {
        (void)close(fd);
        return r;
    }
    ret = close(fd);
    if (ret != 0) {
        int e = errno;
        free(buffer);
        fprintf(stderr, "Error reading %s: %s\n", sourcetoshow,
                strerror(e));
        return RET_ERRNO(e);
    }
    *data = buffer;
    if (len != NULL)
        *len = bufferlen;
    return RET_OK;
}
Beispiel #9
0
/* 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;
}
Beispiel #10
0
retvalue tracking_tidyall(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_WAS_ERROR(r)) {
			result = r;
			break;
		}
		r = trackedpackage_tidy(t, pkg);
		RET_UPDATE(result, r);
		r = tracking_saveatcursor(t, cursor, pkg);
		RET_UPDATE(result, r);
		trackedpackage_free(pkg);
	}
	r = cursor_close(t->table, cursor);
	RET_UPDATE(result, r);
	return result;
}
Beispiel #11
0
retvalue trackingdata_finish(trackingdb tracks, struct trackingdata *d) {
	retvalue r;
	assert (d->tracks == tracks);
	if (d->pkg != NULL) {
		r = trackedpackage_tidy(tracks, d->pkg);
		r = tracking_save(tracks, d->pkg);
	} else
		r = RET_OK;
	d->pkg = NULL;
	/* call for all remembered actions... */
	while (d->remembered != NULL) {
		struct trackingdata_remember *h = d->remembered;
		struct trackedpackage *pkg;
		d->remembered = h->next;
		r = tracking_get(tracks, h->name, h->version, &pkg);
		free(h->name);
		free(h->version);
		free(h);
		if (RET_IS_OK(r)) {
			r = trackedpackage_tidy(tracks, pkg);
			r = tracking_save(tracks, pkg);
		}
	}
	d->tracks = NULL;
	return r;

}
Beispiel #12
0
retvalue files_remove(const char *filekey) {
	retvalue r;

	r = files_removesilent(filekey);
	if (RET_IS_OK(r))
		return pool_markdeleted(filekey);
	return r;
}
Beispiel #13
0
/* add an reference to a file for an identifier. multiple calls */
retvalue references_increment(const char *needed, const char *neededby) {
	retvalue r;

	r = table_addrecord(rdb_references, needed,
			neededby, strlen(neededby), false);
	if (RET_IS_OK(r) && verbose > 8)
		printf("Adding reference to '%s' by '%s'\n", needed, neededby);
	return r;
}
Beispiel #14
0
void markdone_index(struct markdonefile *done, const char *file, const struct checksums *checksums) {
	retvalue r;
	size_t s;
	const char *data;

	r = checksums_getcombined(checksums, &data, &s);
	if (!RET_IS_OK(r))
		return;
	fprintf(done->file, "Index %s %s\n", file, data);
}
Beispiel #15
0
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;
}
Beispiel #16
0
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;
}
Beispiel #17
0
static retvalue files_get_checksums(const char *filekey, /*@out@*/struct checksums **checksums_p) {
	const char *checksums;
	size_t checksumslen;
	retvalue r;

	r = table_gettemprecord(rdb_checksums, filekey,
		&checksums, &checksumslen);
	if (!RET_IS_OK(r))
		return r;
	return checksums_setall(checksums_p, checksums, checksumslen);
}
Beispiel #18
0
static bool comparesourceversion(enum term_comparison c, const struct compare_with *v, const void *d1, const void *d2) {
	const char *control = d1;
	const struct target *target = d2;
	char *package, *source, *version;
	retvalue r;
	bool matches;

	// TODO: make more efficient
	r = chunk_getvalue(control, "Package", &package);
	if (!RET_IS_OK(r))
		return false;
	r = target->getsourceandversion(control, package, &source, &version);
	free(package);
	if (!RET_IS_OK(r))
		return false;
	free(source);
	matches = compare_dpkgversions(c, version, v->pointer);
	free(version);
	return matches;
}
Beispiel #19
0
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;
}
Beispiel #20
0
retvalue tracking_get(trackingdb t, const char *sourcename, const char *version, /*@out@*/struct trackedpackage **pkg) {
	const char *data;
	size_t datalen;
	retvalue r;

	assert (pkg != NULL && sourcename != NULL && version != NULL);

	r = table_getpair(t->table, sourcename, version, &data, &datalen);
	if (!RET_IS_OK(r))
		return r;
	return parse_data(sourcename, version, data, datalen, pkg);
}
Beispiel #21
0
/* check for file in the database and if not found there, if it can be detected */
retvalue files_expect(const char *filekey, const struct checksums *checksums, bool warnifadded) {
	retvalue r;
	char *filename;
	struct checksums *improvedchecksums = NULL;

	r = files_canadd(filekey, checksums);
	if (r == RET_NOTHING)
		return RET_OK;
	if (RET_WAS_ERROR(r))
		return r;

	/* ready to add means missing, so have to look for the file itself: */
	filename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(filename))
		return RET_ERROR_OOM;

	/* first check if a possible manually put (or left over from previous
	 * downloads attepts) file is there and is correct */
	r = checksums_test(filename, checksums, &improvedchecksums);
	if (r == RET_ERROR_WRONG_MD5) {
		fprintf(stderr,
"Deleting unexpected file '%s'!\n"
"(not in database and wrong in pool)\n ",
				filename);
		if (unlink(filename) == 0)
			r = RET_NOTHING;
		else {
			int e = errno;
			fprintf(stderr,
"Error %d deleting '%s': %s!\n", e, filename, strerror(e));
		}
	}
	free(filename);
	if (!RET_IS_OK(r))
		return r;

	if (warnifadded)
		fprintf(stderr,
"Warning: readded existing file '%s' mysteriously missing from the checksum database.\n",
				filekey);

	// TODO: some callers might want the updated checksum when
	// improves is true, how to get them there?

	/* add found file to database */
	if (improvedchecksums != NULL) {
		r = files_add_checksums(filekey, improvedchecksums);
		checksums_free(improvedchecksums);
	} else
		r = files_add_checksums(filekey, checksums);
	assert (r != RET_NOTHING);
	return r;
}
Beispiel #22
0
off_t files_getsize(const char *filekey) {
	retvalue r;
	off_t s;
	struct checksums *checksums;

	r = files_get_checksums(filekey, &checksums);
	if (!RET_IS_OK(r))
		return -1;
	s = checksums_getfilesize(checksums);
	checksums_free(checksums);
	return s;
}
Beispiel #23
0
retvalue tracking_reset(trackingdb t) {
	struct cursor *cursor;
	retvalue result, r;
	struct trackedpackage *pkg;
	const char *key, *value, *data;
	char *newdata;
	size_t datalen, newdatalen;
	int i;

	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)) {
		// this would perhaps be more stable if it just replaced
		// everything within the string just received...
		result = parse_data(key, value, data, datalen, &pkg);
		if (RET_WAS_ERROR(result))
			break;
		for (i = 0 ; i < pkg->filekeys.count ; i++) {
			pkg->refcounts[i] = 0;
		}
		result = gen_data(pkg, &newdata, &newdatalen);
		trackedpackage_free(pkg);
		if (RET_IS_OK(result))
			result = cursor_replace(t->table, cursor,
					newdata, newdatalen);
		free(newdata);
		if (RET_WAS_ERROR(result))
			break;
	}
	r = cursor_close(t->table, cursor);
	RET_UPDATE(result, r);
	return result;
}
Beispiel #24
0
retvalue trackingdata_summon(trackingdb tracks, const char *name, const char *version, struct trackingdata *data) {
	struct trackedpackage *pkg;
	retvalue r;

	r = tracking_getornew(tracks, name, version, &pkg);
	assert (r != RET_NOTHING);
	if (RET_IS_OK(r)) {
		data->tracks = tracks;
		data->pkg = pkg;
		data->remembered = NULL;
		return r;
	}
	return r;
}
Beispiel #25
0
static bool compareversion(enum term_comparison c, const struct compare_with *v, const void *d1, const void *d2) {
	const char *control = d1;
	const struct target *target = d2;
	char *version;
	retvalue r;
	bool matches;

	r = target->getversion(control, &version);
	if (!RET_IS_OK(r))
		return false;
	matches = compare_dpkgversions(c, version, v->pointer);
	free(version);
	return matches;
}
Beispiel #26
0
/* hardlink file with known checksums and add it to database */
retvalue files_hardlinkandadd(const char *tempfile, const char *filekey, const struct checksums *checksums) {
	retvalue r;

	/* an additional check to make sure nothing tricks us into
	 * overwriting it by another file */
	r = files_canadd(filekey, checksums);
	if (!RET_IS_OK(r))
		return r;
	r = checksums_hardlink(global.outdir, filekey, tempfile, checksums);
	if (RET_WAS_ERROR(r))
		return r;

	return files_add_checksums(filekey, checksums);
}
Beispiel #27
0
/***************************Input and Output****************************/
static retvalue logmessage(const struct aptmethod *method, const char *chunk, const char *type) {
	retvalue r;
	char *message;

	r = chunk_getvalue(chunk, "Message", &message);
	if (RET_WAS_ERROR(r))
		return r;
	if (RET_IS_OK(r)) {
		fprintf(stderr, "aptmethod '%s': '%s'\n",
				method->baseuri, message);
		free(message);
		return RET_OK;
	}
	r = chunk_getvalue(chunk, "URI", &message);
	if (RET_WAS_ERROR(r))
		return r;
	if (RET_IS_OK(r)) {
		fprintf(stderr, "aptmethod %s '%s'\n", type, message);
		free(message);
		return RET_OK;
	}
	fprintf(stderr, "aptmethod '%s': '%s'\n", method->baseuri, type);
	return RET_OK;
}
Beispiel #28
0
/* check for several files in the database and update information,
 * return RET_NOTHING if everything is OK and nothing needs improving */
retvalue files_checkorimprove(const struct strlist *filekeys, struct checksums *checksumsarray[]) {
	int i;
	retvalue result, r;

	result = RET_NOTHING;
	for (i = 0 ; i < filekeys->count ; i++) {
		r = checkorimprove(filekeys->values[i],
				&checksumsarray[i]);
		if (RET_WAS_ERROR(r))
			return r;
		if (RET_IS_OK(r))
			result = RET_OK;
	}
	return result;
}
Beispiel #29
0
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;
}
Beispiel #30
0
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;
}