Example #1
0
bool ShaderGLES2::bind() {
		
	if (active!=this || !version || new_conditional_version.key!=conditional_version.key) {
		conditional_version=new_conditional_version;
		version = get_current_version();
	} else {

		return false;
	}
	
	ERR_FAIL_COND_V(!version,false);

	glUseProgram( version->id );

	DEBUG_TEST_ERROR("Use Program");

	active=this;
	uniforms_dirty = true;
/*
 *	why on earth is this code here?
	for (int i=0;i<texunit_pair_count;i++) {

		glUniform1i(texunit_pairs[i].location, texunit_pairs[i].index);
		DEBUG_TEST_ERROR("Uniform 1 i");
	}

*/
	return true;
}
Example #2
0
void read_versions(int *current_version,
		   int *server_version,
		   char *path_prefix)
{
	*current_version = get_current_version(path_prefix);

	*server_version = get_latest_version();
}
Example #3
0
/* Check if the version argument is the same version as the current OS */
bool is_current_version(int version)
{
	if (version < 0) {
		return false;
	}

	return (version == get_current_version(path_prefix));
}
Example #4
0
/* This is only called from init paths, so printing an error message is
 * appropriate if something goes wrong */
TSS_RESULT
get_tpm_metrics(struct tpm_properties *p)
{
	TSS_RESULT result;
	UINT32 subCap, rv = 0;

	if ((result = get_current_version(&p->version)))
		goto err;

	UINT32ToArray(TPM_ORD_SaveKeyContext, (BYTE *)&subCap);
	if ((result = get_cap_uint32(TCPA_CAP_ORD, (BYTE *)&subCap, sizeof(UINT32), &rv)))
		goto err;
	p->keyctx_swap = rv ? TRUE : FALSE;

	rv = 0;
	UINT32ToArray(TPM_ORD_SaveAuthContext, (BYTE *)&subCap);
	if ((result = get_cap_uint32(TCPA_CAP_ORD, (BYTE *)&subCap, sizeof(UINT32), &rv)))
		goto err;
	p->authctx_swap = rv ? TRUE : FALSE;

	UINT32ToArray(TPM_CAP_PROP_PCR, (BYTE *)&subCap);
	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
					&p->num_pcrs)))
		goto err;

	UINT32ToArray(TPM_CAP_PROP_DIR, (BYTE *)&subCap);
	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
					&p->num_dirs)))
		goto err;

	UINT32ToArray(TPM_CAP_PROP_SLOTS, (BYTE *)&subCap);
	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
					&p->num_keys)))
		goto err;

	UINT32ToArray(TPM_CAP_PROP_MANUFACTURER, (BYTE *)&subCap);
	if ((result = get_cap_uint32(TCPA_CAP_PROPERTY, (BYTE *)&subCap, sizeof(UINT32),
					(UINT32 *)&p->manufacturer)))
		goto err;

	result = get_max_auths(&(p->num_auths));

err:
	if (result)
		LogError("TCS GetCapability failed with result = 0x%x", result);

	return result;
}
Example #5
0
enum swupd_code read_versions(int *current_version, int *server_version, char *path_prefix)
{
	*current_version = get_current_version(path_prefix);
	*server_version = get_latest_version(NULL);

	if (*current_version < 0) {
		error("Unable to determine current OS version\n");
		return SWUPD_CURRENT_VERSION_UNKNOWN;
	}
	if (*server_version < 0) {
		error("Unable to determine the server version\n");
		return SWUPD_SERVER_CONNECTION_ERROR;
	}

	return SWUPD_OK;
}
Example #6
0
int read_versions(int *current_version, int *server_version, char *path_prefix)
{
	*current_version = get_current_version(path_prefix);
	*server_version = get_latest_version(NULL);

	if (*current_version < 0) {
		fprintf(stderr, "Error: Unable to determine current OS version\n");
		return ECURRENT_VERSION;
	}
	if (*server_version < 0) {
		fprintf(stderr, "Error: Unable to determine the server version\n");
		return ENOSWUPDSERVER;
	}

	return 0;
}
Example #7
0
bool ShaderGLES2::bind() {

	if (active != this || !version || new_conditional_version.key != conditional_version.key) {
		conditional_version = new_conditional_version;
		version = get_current_version();
	} else {
		return false;
	}

	ERR_FAIL_COND_V(!version, false);

	if (!version->ok) { //broken, unable to bind (do not throw error, you saw it before already when it failed compilation).
		glUseProgram(0);
		return false;
	}

	glUseProgram(version->id);

	// find out uniform names and locations

	int count;
	glGetProgramiv(version->id, GL_ACTIVE_UNIFORMS, &count);
	version->uniform_names.resize(count);

	for (int i = 0; i < count; i++) {
		GLchar uniform_name[1024];
		int len = 0;
		GLint size = 0;
		GLenum type;

		glGetActiveUniform(version->id, i, 1024, &len, &size, &type, uniform_name);

		uniform_name[len] = '\0';
		String name = String((const char *)uniform_name);

		version->uniform_names.write[i] = name;
	}

	bind_uniforms();

	DEBUG_TEST_ERROR("use program");

	active = this;
	uniforms_dirty = true;

	return true;
}
Example #8
0
/*
* list_installable_bundles()
* Parse the full manifest for the current version of the OS and print
*   all available bundles.
*/
int list_installable_bundles()
{
	struct list *list;
	struct file *file;
	struct manifest *MoM = NULL;
	int current_version;
	int lock_fd;
	int ret;

	ret = swupd_init(&lock_fd);
	if (ret != 0) {
		printf("Error: Failed updater initialization. Exiting now\n");
		return ret;
	}

	if (!check_network()) {
		printf("Error: Network issue, unable to download manifest\n");
		v_lockfile(lock_fd);
		return EXIT_FAILURE;
	}

	current_version = get_current_version(path_prefix);
	if (current_version < 0) {
		printf("Error: Unable to determine current OS version\n");
		v_lockfile(lock_fd);
		return ECURRENT_VERSION;
	}

	swupd_curl_set_current_version(current_version);

	MoM = load_mom(current_version);
	if (!MoM) {
		v_lockfile(lock_fd);
		return ret;
	}

	list = MoM->manifests;
	while (list) {
		file = list->data;
		list = list->next;
		printf("%s\n", file->filename);
	}

	free_manifest(MoM);
	v_lockfile(lock_fd);
	return 0;
}
Example #9
0
int info_main(int UNUSED_PARAM argc, char UNUSED_PARAM **argv)
{
	int current_version;

	copyright_header("info");

	if (!init_globals()) {
		return EINIT_GLOBALS;
	}

	current_version = get_current_version(path_prefix);
	printf("Installed version: %d\n", current_version);
	printf("Version URL:       %s\n", version_url);
	printf("Content URL:       %s\n", content_url);

	free_globals();
	return 0;
}
Example #10
0
/* Bundle install one ore more bundles passed in bundles
 * param as a null terminated array of strings
 */
int install_bundles_frontend(char **bundles)
{
	int lock_fd;
	int ret = 0;
	int current_version;
	struct list *bundles_list = NULL;
	struct manifest *mom;

	/* initialize swupd and get current version from OS */
	ret = swupd_init(&lock_fd);
	if (ret != 0) {
		printf("Failed updater initialization, exiting now.\n");
		return ret;
	}

	current_version = get_current_version(path_prefix);
	if (current_version < 0) {
		printf("Error: Unable to determine current OS version\n");
		ret = ECURRENT_VERSION;
		goto clean_and_exit;
	}

	swupd_curl_set_current_version(current_version);

	mom = load_mom(current_version);
	if (!mom) {
		printf("Cannot load official manifest MoM for version %i\n", current_version);
		ret = EMOM_NOTFOUND;
		goto clean_and_exit;
	}

	for (; *bundles; ++bundles) {
		bundles_list = list_prepend_data(bundles_list, *bundles);
	}

	ret = install_bundles(bundles_list, current_version, mom);
	list_free_list(bundles_list);

	free_manifest(mom);
clean_and_exit:
	swupd_deinit(lock_fd);

	return ret;
}
Example #11
0
bool ShaderGLES2::bind() {

	if (active != this || !version || new_conditional_version.key != conditional_version.key) {
		conditional_version = new_conditional_version;
		version = get_current_version();
	} else {
		return false;
	}

	ERR_FAIL_COND_V(!version, false);

	glUseProgram(version->id);

	DEBUG_TEST_ERROR("use program");

	active = this;
	uniforms_dirty = true;

	return true;
}
Example #12
0
bool version_files_consistent(void)
{
	/*
	 * Compare version numbers in state_dir/version and /usr/lib/os-release.
	 * The version in /usr/lib/os-release must match or be greater than
	 * state_dir/version for successful updates (greater than occurs during
	 * format bumps).
	 */
	int os_release_v = -1;
	int state_v = -1;
	char *state_v_path;

	string_or_die(&state_v_path, "%s/version", state_dir);
	os_release_v = get_current_version(path_prefix);
	state_v = get_version_from_path(state_v_path);
	free_string(&state_v_path);

	// -1 returns indicate failures
	if (os_release_v < 0 || state_v < 0) {
		return false;
	}

	return (os_release_v >= state_v);
}
Example #13
0
/*  This function is a fresh new implementation for a bundle
 *  remove without being tied to verify loop, this means
 *  improved speed and space as well as more roubustness and
 *  flexibility. What it does is basically:
 *
 *  1) Read MoM and load all submanifests except the one to be
 *  	removed and then consolidate them.
 *  2) Load the removed bundle submanifest.
 *  3) Order the file list by filename
 *  4) Deduplicate removed submanifest file list that happens
 *  	to be on the MoM (minus bundle to be removed).
 *  5) iterate over to be removed bundle submanifest file list
 *  	performing a unlink(2) for each filename.
 *  6) Done.
 */
int remove_bundle(const char *bundle_name)
{
	int lock_fd;
	int ret = 0;
	int current_version = CURRENT_OS_VERSION;
	struct manifest *current_mom, *bundle_manifest = NULL;

	ret = swupd_init(&lock_fd);
	if (ret != 0) {
		printf("Failed updater initialization, exiting now.\n");
		return ret;
	}

	/* os-core bundle not allowed to be removed...
	 * although this is going to be caught later because of all files
	 * being marked as 'duplicated' and note removing anything
	 * anyways, better catch here and return success, no extra work to be done.
	 */
	if (strcmp(bundle_name, "os-core") == 0) {
		ret = EBUNDLE_NOT_TRACKED;
		goto out_free_curl;
	}

	if (!is_tracked_bundle(bundle_name)) {
		ret = EBUNDLE_NOT_TRACKED;
		goto out_free_curl;
	}

	current_version = get_current_version(path_prefix);
	if (current_version < 0) {
		printf("Error: Unable to determine current OS version\n");
		ret = ECURRENT_VERSION;
		goto out_free_curl;
	}

	swupd_curl_set_current_version(current_version);

	current_mom = load_mom(current_version);
	if (!current_mom) {
		printf("Unable to download/verify %d Manifest.MoM\n", current_version);
		ret = EMOM_NOTFOUND;
		goto out_free_curl;
	}

	if (!search_bundle_in_manifest(current_mom, bundle_name)) {
		printf("Bundle name is invalid, aborting removal\n");
		ret = EBUNDLE_REMOVE;
		goto out_free_mom;
	}

	/* load all tracked bundles into memory */
	read_subscriptions_alt();
	/* now popout the one to be removed */
	ret = unload_tracked_bundle(bundle_name);
	if (ret != 0) {
		goto out_free_mom;
	}

	subscription_versions_from_MoM(current_mom, 0);

	/* load all submanifest minus the one to be removed */
	current_mom->submanifests = recurse_manifest(current_mom, NULL);
	if (!current_mom->submanifests) {
		printf("Error: Cannot load MoM sub-manifests\n");
		ret = ERECURSE_MANIFEST;
		goto out_free_mom;
	}

	if (is_included(bundle_name, current_mom)) {
		printf("Error: bundle requested to be removed is required by other installed bundles\n");
		ret = EBUNDLE_REMOVE;
		goto out_free_mom;
	}

	current_mom->files = files_from_bundles(current_mom->submanifests);

	current_mom->files = consolidate_files(current_mom->files);

	/* Now that we have the consolidated list of all files, load bundle to be removed submanifest*/
	ret = load_bundle_manifest(bundle_name, current_version, &bundle_manifest);
	if (ret != 0 || !bundle_manifest) {
		printf("Error: Cannot load %s sub-manifest (ret = %d)\n", bundle_name, ret);
		goto out_free_mom;
	}

	/* deduplication needs file list sorted by filename, do so */
	bundle_manifest->files = list_sort(bundle_manifest->files, file_sort_filename);
	deduplicate_files_from_manifest(&bundle_manifest, current_mom);

	printf("Deleting bundle files...\n");
	remove_files_in_manifest_from_fs(bundle_manifest);

	printf("Untracking bundle from system...\n");
	rm_bundle_file(bundle_name);

	printf("Success: Bundle removed\n");

	free_manifest(bundle_manifest);
out_free_mom:
	free_manifest(current_mom);
out_free_curl:

	if (ret) {
		printf("Error: Bundle remove failed\n");
	}

	swupd_deinit(lock_fd);

	return ret;
}
Example #14
0
/* download_manifests()
 * Description: To search Clear bundles for a particular entry, a complete set of
 *		manifests must be downloaded. This function does so, asynchronously, using
 *		the curl_multi interface */
static int download_manifests(struct manifest **MoM, struct list **subs)
{
	struct list *list = NULL;
	struct file *file = NULL;
	char *tarfile, *untard_file, *url = NULL;
	struct manifest *subMan = NULL;
	int current_version;
	int ret = 0;
	double size;
	bool did_download = false;

	current_version = get_current_version(path_prefix);
	if (current_version < 0) {
		fprintf(stderr, "Error: Unable to determine current OS version\n");
		return ECURRENT_VERSION;
	}

	*MoM = load_mom(current_version, false, false, NULL);
	if (!(*MoM)) {
		fprintf(stderr, "Cannot load official manifest MoM for version %i\n", current_version);
		return EMOM_LOAD;
	}

	list = (*MoM)->manifests;
	size = query_total_download_size(list);
	if (size == -1) {
		fprintf(stderr, "Downloading manifests. Expect a delay, up to 100MB may be downloaded\n");
	} else if (size > 0) {
		fprintf(stderr, "Downloading Clear Linux manifests\n");
		fprintf(stderr, "   %.2f MB total...\n\n", size);
	}

	while (list) {
		file = list->data;
		list = list->next;

		create_and_append_subscription(subs, file->filename);

		string_or_die(&untard_file, "%s/%i/Manifest.%s", state_dir, file->last_change,
			      file->filename);

		string_or_die(&tarfile, "%s/%i/Manifest.%s.tar", state_dir, file->last_change,
			      file->filename);

		if (access(untard_file, F_OK) == -1) {
			/* Do download */
			subMan = load_manifest(file->last_change, file, *MoM, false);
			if (!subMan) {
				fprintf(stderr, "Cannot load official manifest MoM for version %i\n", current_version);
			} else {
				did_download = true;
			}

			free_manifest(subMan);
		}

		if (access(untard_file, F_OK) == -1) {
			string_or_die(&url, "%s/%i/Manifest.%s.tar", content_url, current_version,
				      file->filename);

			fprintf(stderr, "Error: Failure reading from %s\n", url);
			free_string(&url);
		}

		unlink(tarfile);
		free_string(&untard_file);
		free_string(&tarfile);
	}

	if (did_download) {
		fprintf(stderr, "Completed manifests download.\n\n");
	}

	return ret;
}
Example #15
0
/* This function does a simple verification of files listed in the
 * subscribed bundle manifests.  If the optional "fix" or "install" parameter
 * is specified, the disk will be modified at each point during the
 * sequential comparison of manifest files to disk files, where the disk is
 * found to not match the manifest.  This is notably different from update,
 * which attempts to atomically (or nearly atomically) activate a set of
 * pre-computed and validated staged changes as a group. */
int verify_main(int argc, char **argv)
{
	struct manifest *official_manifest = NULL;
	int ret;
	int lock_fd;
	struct list *subs = NULL;

	copyright_header("software verify");

	if (!parse_options(argc, argv)) {
		return EINVALID_OPTION;
	}

	/* parse command line options */
	assert(argc >= 0);
	assert(argv != NULL);

	ret = swupd_init(&lock_fd);
	if (ret != 0) {
		printf("Failed verify initialization, exiting now.\n");
		return ret;
	}

	/* Gather current manifests */
	if (!version) {
		version = get_current_version(path_prefix);
		if (version < 0) {
			printf("Error: Unable to determine current OS version\n");
			ret = ECURRENT_VERSION;
			goto clean_and_exit;
		}
	}

	if (version == -1) {
		version = get_latest_version();
		if (version < 0) {
			printf("Unable to get latest version for install\n");
			ret = EXIT_FAILURE;
			goto clean_and_exit;
		}
	}

	printf("Verifying version %i\n", version);

	if (!check_network()) {
		printf("Error: Network issue, unable to download manifest\n");
		ret = ENOSWUPDSERVER;
		goto clean_and_exit;
	}

	read_subscriptions_alt(&subs);

	/*
	 * FIXME: We need a command line option to override this in case the
	 * certificate is hosed and the admin knows it and wants to recover.
	 */

	ret = rm_staging_dir_contents("download");
	if (ret != 0) {
		printf("Failed to remove prior downloads, carrying on anyway\n");
	}

	official_manifest = load_mom(version);

	if (!official_manifest) {
		/* This is hit when or if an OS version is specified for --fix which
		 * is not available, or if there is a server error and a manifest is
		 * not provided.
		 */
		printf("Unable to download/verify %d Manifest.MoM\n", version);
		ret = EMOM_NOTFOUND;

		/* No repair is possible without a manifest, nor is accurate reporting
		 * of the state of the system. Therefore cleanup, report failure and exit
		 */
		goto clean_and_exit;
	}

	ret = add_included_manifests(official_manifest, &subs);
	if (ret) {
		ret = EMANIFEST_LOAD;
		goto clean_and_exit;
	}

	set_subscription_versions(official_manifest, NULL, &subs);

	official_manifest->submanifests = recurse_manifest(official_manifest, subs, NULL);
	if (!official_manifest->submanifests) {
		printf("Error: Cannot load MoM sub-manifests\n");
		ret = ERECURSE_MANIFEST;
		goto clean_and_exit;
	}
	official_manifest->files = files_from_bundles(official_manifest->submanifests);

	official_manifest->files = consolidate_files(official_manifest->files);

	/* when fixing or installing we need input files. */
	if (cmdline_option_fix || cmdline_option_install) {
		ret = get_required_files(official_manifest, subs);
		if (ret != 0) {
			ret = -ret;
			goto clean_and_exit;
		}
	}

	/* preparation work complete. */

	/*
	 * NOTHING ELSE IS ALLOWED TO FAIL/ABORT after this line.
	 * This tool is there to recover a nearly-bricked system. Aborting
	 * from this point forward, for any reason, will result in a bricked system.
	 *
	 * I don't care what your static analysis tools says
	 * I don't care what valgrind tells you
	 *
	 * There shall be no "goto fail;" from this point on.
	 *
	 *   *** THE SHOW MUST GO ON ***
	 */

	if (cmdline_option_fix || cmdline_option_install) {
		/*
		 * Next put the files in place that are missing completely.
		 * This is to avoid updating a symlink to a library before the new full file
		 * is already there. It's also the most safe operation, adding files rarely
		 * has unintended side effect. So lets do the safest thing first.
		 */
		printf("Adding any missing files\n");
		add_missing_files(official_manifest);
	}

	if (cmdline_option_quick) {
		/* quick only replaces missing files, so it is done here */
		goto brick_the_system_and_clean_curl;
	}

	if (cmdline_option_fix) {
		bool repair = true;

		printf("Fixing modified files\n");
		deal_with_hash_mismatches(official_manifest, repair);

		/* removing files could be risky, so only do it if the
		 * prior phases had no problems */
		if ((file_not_fixed_count == 0) && (file_not_replaced_count == 0)) {
			remove_orphaned_files(official_manifest);
		}
	} else {
		bool repair = false;

		printf("Verifying files\n");
		deal_with_hash_mismatches(official_manifest, repair);
	}
	free_manifest(official_manifest);

brick_the_system_and_clean_curl:
	/* clean up */

	/*
	 * naming convention: All exit goto labels must follow the "brick_the_system_and_FOO:" pattern
	 */

	/* report a summary of what we managed to do and not do */
	printf("Inspected %i files\n", file_checked_count);

	if (cmdline_option_fix || cmdline_option_install) {
		printf("  %i files were missing\n", file_missing_count);
		if (file_missing_count) {
			printf("    %i of %i missing files were replaced\n", file_replaced_count, file_missing_count);
			printf("    %i of %i missing files were not replaced\n", file_not_replaced_count, file_missing_count);
		}
	}

	if (!cmdline_option_quick && file_mismatch_count > 0) {
		printf("  %i files did not match\n", file_mismatch_count);
		if (cmdline_option_fix) {
			printf("    %i of %i files were fixed\n", file_fixed_count, file_mismatch_count);
			printf("    %i of %i files were not fixed\n", file_not_fixed_count, file_mismatch_count);
		}
	}

	if ((file_not_fixed_count == 0) && (file_not_replaced_count == 0) &&
	    cmdline_option_fix && !cmdline_option_quick) {
		printf("  %i files found which should be deleted\n", file_extraneous_count);
		if (file_extraneous_count) {
			printf("    %i of %i files were deleted\n", file_deleted_count, file_extraneous_count);
			printf("    %i of %i files were not deleted\n", file_not_deleted_count, file_extraneous_count);
		}
	}

	if (cmdline_option_fix || cmdline_option_install) {
		// always run in a fix or install case
		need_update_boot = true;
		need_update_bootloader = true;
		run_scripts();
	}

	sync();

	if ((file_not_fixed_count == 0) &&
	    (file_not_replaced_count == 0) &&
	    (file_not_deleted_count == 0)) {
		ret = EXIT_SUCCESS;
	} else {
		ret = EXIT_FAILURE;
	}

/* this concludes the critical section, after this point it's clean up time, the disk content is finished and final */

clean_and_exit:
	telemetry(ret ? TELEMETRY_CRIT : TELEMETRY_INFO,
		  "verify",
		  "fix=%d\nret=%d\n"
		  "current_version=%d\n"
		  "file_replaced_count=%d\n"
		  "file_not_replaced_count=%d\n"
		  "file_missing_count=%d\n"
		  "file_fixed_count=%d\n"
		  "file_not_fixed_count=%d\n"
		  "file_deleted_count=%d\n"
		  "file_not_deleted_count=%d\n"
		  "file_mismatch_count=%d\n"
		  "file_extraneous_count=%d\n",
		  cmdline_option_fix || cmdline_option_install,
		  ret,
		  version,
		  file_replaced_count,
		  file_not_replaced_count,
		  file_missing_count,
		  file_fixed_count,
		  file_not_fixed_count,
		  file_deleted_count,
		  file_not_deleted_count,
		  file_mismatch_count,
		  file_extraneous_count);
	if (ret == EXIT_SUCCESS) {
		if (cmdline_option_fix || cmdline_option_install) {
			printf("Fix successful\n");
		} else {
			/* This is just a verification */
			printf("Verify successful\n");
		}
	} else {
		if (cmdline_option_fix || cmdline_option_install) {
			printf("Error: Fix did not fully succeed\n");
		} else {
			/* This is just a verification */
			printf("Error: Verify did not fully succeed\n");
		}
	}

	swupd_deinit(lock_fd, &subs);

	return ret;
}
Example #16
0
mtx_release_version_t::mtx_release_version_t()
  : current_version(get_current_version())
  , valid(false)
{
}
Example #17
0
static enum swupd_code clean_staged_manifests(const char *path, bool dry_run, bool all)
{
	DIR *dir;

	dir = opendir(path);
	if (!dir) {
		return SWUPD_COULDNT_LIST_DIR;
	}

	/* NOTE: Currently Manifest files have their timestamp from generation
	 * preserved. */

	/* When --all is not used, keep the Manifests used by the current OS version. This
	 * ensures that a regular 'clean' won't make 'search' redownload files. */
	char *mom_contents = NULL;
	if (!all) {
		int current_version = get_current_version(path_prefix);
		if (current_version < 0) {
			warn("Unable to determine current OS version\n");
		} else {
			mom_contents = read_mom_contents(current_version);
		}
	}

	int ret = SWUPD_OK;
	while (true) {
		/* Reset errno to properly identify the end of stream. */
		errno = 0;
		struct dirent *entry;
		entry = readdir(dir);
		if (!entry) {
			if (errno) {
				ret = SWUPD_COULDNT_LIST_DIR;
			}
			break;
		}

		const char *name = entry->d_name;
		if (!strcmp(name, ".") || !strcmp(name, "..")) {
			continue;
		}
		if (!is_all_digits(name)) {
			continue;
		}

		char *version_dir;
		string_or_die(&version_dir, "%s/%s", state_dir, name);

		/* This is not precise: it may keep Manifest files that we don't use, and
		 * also will keep the previous version. If that extra precision is
		 * required we should parse the manifest. */
		if (mom_contents && strstr(mom_contents, name)) {
			/* Remove all hash-hint manifest files. */
			ret = remove_if(version_dir, dry_run, is_hashed_manifest);
		} else {
			/* Remove all manifest files, including hash-hints */
			ret = remove_if(version_dir, dry_run, is_manifest);
		}

		/* Remove empty dirs if possible. */
		(void)rmdir(version_dir);

		free_string(&version_dir);
		if (ret != 0) {
			break;
		}
	}

	free(mom_contents);
	closedir(dir);
	return ret;
}