*/
plugin_t *plugin;
+ /**
+ * TRUE, if the plugin is marked as critical
+ */
+ bool critical;
+
/**
* dlopen handle, if in separate lib
*/
* FAILED, if the plugin could not be constructed
*/
static status_t create_plugin(private_plugin_loader_t *this, void *handle,
- char *name, bool integrity, plugin_entry_t **entry)
+ char *name, bool integrity, bool critical,
+ plugin_entry_t **entry)
{
char create[128];
plugin_t *plugin;
}
INIT(*entry,
.plugin = plugin,
+ .critical = critical,
.loaded = linked_list_create(),
.failed = linked_list_create(),
);
/**
* load a single plugin
*/
-static bool load_plugin(private_plugin_loader_t *this, char *name, char *file)
+static bool load_plugin(private_plugin_loader_t *this, char *name, char *file,
+ bool critical)
{
plugin_entry_t *entry;
void *handle;
- switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, &entry))
+ switch (create_plugin(this, RTLD_DEFAULT, name, FALSE, critical, &entry))
{
case SUCCESS:
this->plugins->insert_last(this->plugins, entry);
DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror());
return FALSE;
}
- if (create_plugin(this, handle, name, TRUE, &entry) != SUCCESS)
+ if (create_plugin(this, handle, name, TRUE, critical, &entry) != SUCCESS)
{
dlclose(handle);
return FALSE;
return unloaded;
}
+/**
+ * Check that we have all features loaded for critical plugins
+ */
+static bool missing_critical_features(private_plugin_loader_t *this)
+{
+ enumerator_t *enumerator;
+ plugin_entry_t *entry;
+ bool critical_failed = FALSE;
+
+ enumerator = this->plugins->create_enumerator(this->plugins);
+ while (enumerator->enumerate(enumerator, &entry))
+ {
+ if (!entry->plugin->get_features)
+ { /* feature interface not supported */
+ continue;
+ }
+ if (entry->critical)
+ {
+ plugin_feature_t *feature;
+ char *name, *provide;
+ int count, i, failed = 0;
+
+ name = entry->plugin->get_name(entry->plugin);
+ count = entry->plugin->get_features(entry->plugin, &feature);
+ for (i = 0; i < count; i++, feature++)
+ {
+ if (feature->kind == FEATURE_PROVIDE &&
+ !feature_loaded(this, entry, feature))
+ {
+ provide = plugin_feature_get_string(feature);
+ DBG2(DBG_LIB, " failed to load %s in critical plugin '%s'",
+ provide, name);
+ free(provide);
+ failed++;
+ }
+ }
+ if (failed)
+ {
+ DBG1(DBG_LIB, "failed to load %d feature%s in critical plugin "
+ "'%s'", failed, failed > 1 ? "s" : "", name);
+ critical_failed = TRUE;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return critical_failed;
+}
+
/**
* Remove plugins that we were not able to load any features from.
*/
{
return FALSE;
}
- if (!load_plugin(this, token, file) && critical)
+ if (!load_plugin(this, token, file, critical) && critical)
{
critical_failed = TRUE;
DBG1(DBG_LIB, "loading critical plugin '%s' failed", token);
}
/* report missing dependencies */
load_features(this, FALSE, TRUE);
+ /* check for unloaded features provided by critical plugins */
+ critical_failed = missing_critical_features(this);
/* unload plugins that we were not able to load any features for */
purge_plugins(this);
}