Ejemplo n.º 1
0
/* create dirname and any '/'-separated part of it */
retvalue dirs_make_recursive(const char *directory) {
	retvalue r, result;

	if (interrupted()) {
		return RET_ERROR_INTERRUPTED;
	}
	r = dirs_make_parent(directory);
	result = dirs_create(directory);
	RET_UPDATE(result, r);
	return result;
}
Ejemplo n.º 2
0
retvalue files_checkincludefile(const char *sourcedir, const char *basefilename, const char *filekey, struct checksums **checksums_p) {
	char *sourcefilename, *fullfilename;
	struct checksums *checksums;
	retvalue r;
	bool improves;

	assert (*checksums_p != NULL);

	r = files_get_checksums(filekey, &checksums);
	if (RET_WAS_ERROR(r))
		return r;
	if (RET_IS_OK(r)) {
		/* there are three sources now:
		 *  - the checksums from the database (may have some we
		 *    do not even know about, and may miss some we can
		 *    generate)
		 *  - the checksums provided (typically only md5sum,
		 *    as this comes from a .changes or .dsc)
		 *  - the checksums of the file
		 *
		 *  to make things more complicated, the file should only
		 *  be read if needed, as this needs time.
		 *  And it can happen the file got lost in the pool, then
		 *  this is the best place to replace it.
		 */
		if (!checksums_check(checksums, *checksums_p, &improves)) {
			fprintf(stderr,
"ERROR: '%s/%s' cannot be included as '%s'.\n"
"Already existing files can only be included again, if they are the same, but:\n",
				sourcedir, basefilename, filekey);
			checksums_printdifferences(stderr, checksums,
					*checksums_p);
			checksums_free(checksums);
			return RET_ERROR_WRONG_MD5;
		}
		r = RET_NOTHING;
		if (improves)
			r = checksums_combine(&checksums, *checksums_p, NULL);
		if (!RET_WAS_ERROR(r))
			r = checkimproveorinclude(sourcedir,
				basefilename, filekey, &checksums, &improves);
		if (!RET_WAS_ERROR(r) && improves)
			r = files_replace_checksums(filekey, checksums);
		if (RET_IS_OK(r))
			r = RET_NOTHING;
		/* return the combined checksum */
		checksums_free(*checksums_p);
		*checksums_p = checksums;
		return r;
	}

	assert (sourcedir != NULL);
	sourcefilename = calc_dirconcat(sourcedir, basefilename);
	if (FAILEDTOALLOC(sourcefilename))
		return RET_ERROR_OOM;

	fullfilename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(fullfilename)) {
		free(sourcefilename);
		return RET_ERROR_OOM;
	}

	(void)dirs_make_parent(fullfilename);
	r = checksums_copyfile(fullfilename, sourcefilename, true, &checksums);
	if (r == RET_NOTHING) {
		fprintf(stderr, "Could not open '%s'!\n", sourcefilename);
		r = RET_ERROR_MISSING;
	}
	if (RET_WAS_ERROR(r)) {
		free(fullfilename);
		free(sourcefilename);
		return r;
	}
	if (!checksums_check(*checksums_p, checksums, &improves)) {
		deletefile(fullfilename);
		fprintf(stderr, "ERROR: Unexpected content of file '%s'!\n",
				sourcefilename);
		checksums_printdifferences(stderr, *checksums_p, checksums);
		r = RET_ERROR_WRONG_MD5;
	}
	free(sourcefilename);
	free(fullfilename);
	if (RET_WAS_ERROR(r)) {
		return r;
	}
	if (improves) {
		r = checksums_combine(checksums_p, checksums, NULL);
		checksums_free(checksums);
		if (RET_WAS_ERROR(r))
			return r;
	} else
		checksums_free(checksums);

	return files_add_checksums(filekey, *checksums_p);
}
Ejemplo n.º 3
0
static retvalue checkimproveorinclude(const char *sourcedir, const char *basefilename, const char *filekey, struct checksums **checksums_p, bool *improving) {
	retvalue r;
	struct checksums *checksums = NULL;
	bool improves, copied = false;
	char *fullfilename = files_calcfullfilename(filekey);

	if (FAILEDTOALLOC(fullfilename))
		return RET_ERROR_OOM;

	if (checksums_iscomplete(*checksums_p)) {
		r = checksums_cheaptest(fullfilename, *checksums_p, true);
		if (r != RET_NOTHING) {
			free(fullfilename);
			return r;
		}
	} else {
		r = checksums_read(fullfilename, &checksums);
		if (RET_WAS_ERROR(r)) {
			free(fullfilename);
			return r;
		}
	}
	if (r == RET_NOTHING) {
		char *sourcefilename = calc_dirconcat(sourcedir, basefilename);

		if (FAILEDTOALLOC(sourcefilename)) {
			free(fullfilename);
			return RET_ERROR_OOM;
		}

		fprintf(stderr,
"WARNING: file %s was lost!\n"
"(i.e. found in the database, but not in the pool)\n"
"trying to compensate...\n",
				filekey);
		(void)dirs_make_parent(fullfilename);
		r = checksums_copyfile(fullfilename, sourcefilename, false,
				&checksums);
		if (r == RET_ERROR_EXIST) {
			fprintf(stderr,
"File '%s' seems to be missing and existing at the same time!\n"
"To confused to continue...\n",
					fullfilename);
		}
		if (r == RET_NOTHING) {
			fprintf(stderr, "Could not open '%s'!\n",
					sourcefilename);
			r = RET_ERROR_MISSING;
		}
		free(sourcefilename);
		if (RET_WAS_ERROR(r)) {
			free(fullfilename);
			return r;
		}
		copied = true;
	}

	assert (checksums != NULL);

	if (!checksums_check(*checksums_p, checksums, &improves)) {
		if (copied) {
			deletefile(fullfilename);
			fprintf(stderr,
"ERROR: Unexpected content of file '%s/%s'!\n", sourcedir, basefilename);
		} else
// TODO: if the database only listed some of the currently supported checksums,
// and the caller of checkincludefile supplied some (which none yet does), but
// not all (which needs at least three checksums, i.e. not applicaple before
// sha256 get added), then this might also be called if the file in the pool
// just has the same checksums as previously recorded (e.g. a md5sum collision)
// but the new file was listed with another secondary hash than the original.
// In that situation it might be a bit misleading...
			fprintf(stderr,
"ERROR: file %s is damaged!\n"
"(i.e. found in the database, but with different checksums in the pool)\n",
				filekey);
		checksums_printdifferences(stderr, *checksums_p, checksums);
		r = RET_ERROR_WRONG_MD5;
	}
	if (improves) {
		r = checksums_combine(checksums_p, checksums, NULL);
		if (RET_IS_OK(r))
			*improving = true;
	}
	checksums_free(checksums);
	free(fullfilename);
	return r;
}
Ejemplo n.º 4
0
/* Include a yet unknown file into the pool */
retvalue files_preinclude(const char *sourcefilename, const char *filekey, struct checksums **checksums_p) {
	retvalue r;
	struct checksums *checksums, *realchecksums;
	bool improves;
	char *fullfilename;

	r = files_get_checksums(filekey, &checksums);
	if (RET_WAS_ERROR(r))
		return r;
	if (RET_IS_OK(r)) {
		r = checksums_read(sourcefilename, &realchecksums);
		if (r == RET_NOTHING)
			r = RET_ERROR_MISSING;
		if (RET_WAS_ERROR(r)) {
			checksums_free(checksums);
			return r;
		}
		if (!checksums_check(checksums, realchecksums, &improves)) {
			fprintf(stderr,
"ERROR: '%s' cannot be included as '%s'.\n"
"Already existing files can only be included again, if they are the same, but:\n",
				sourcefilename, filekey);
			checksums_printdifferences(stderr, checksums,
					realchecksums);
			checksums_free(checksums);
			checksums_free(realchecksums);
			return RET_ERROR_WRONG_MD5;
		}
		if (improves) {
			r = checksums_combine(&checksums, realchecksums, NULL);
			if (RET_WAS_ERROR(r)) {
				checksums_free(realchecksums);
				checksums_free(checksums);
				return r;
			}
			r = files_replace_checksums(filekey, checksums);
			if (RET_WAS_ERROR(r)) {
				checksums_free(realchecksums);
				checksums_free(checksums);
				return r;
			}
		}
		checksums_free(realchecksums);
		// args, this breaks retvalue semantics!
		if (checksums_p != NULL)
			*checksums_p = checksums;
		else
			checksums_free(checksums);
		return RET_NOTHING;
	}
	assert (sourcefilename != NULL);
	fullfilename = files_calcfullfilename(filekey);
	if (FAILEDTOALLOC(fullfilename))
		return RET_ERROR_OOM;
	(void)dirs_make_parent(fullfilename);
	r = checksums_copyfile(fullfilename, sourcefilename, true, &checksums);
	if (r == RET_ERROR_EXIST) {
		// TODO: deal with already existing files!
		fprintf(stderr, "File '%s' does already exist!\n",
				fullfilename);
	}
	if (r == RET_NOTHING) {
		fprintf(stderr, "Could not open '%s'!\n", sourcefilename);
		r = RET_ERROR_MISSING;
	}
	if (RET_WAS_ERROR(r)) {
		free(fullfilename);
		return r;
	}
	free(fullfilename);

	r = files_add_checksums(filekey, checksums);
	if (RET_WAS_ERROR(r)) {
		checksums_free(checksums);
		return r;
	}
	if (checksums_p != NULL)
		*checksums_p = checksums;
	else
		checksums_free(checksums);
	return RET_OK;
}