diff --git a/doc/gvmd.html b/doc/gvmd.html
index 103199801..981f1e0d8 100644
--- a/doc/gvmd.html
+++ b/doc/gvmd.html
@@ -276,8 +276,20 @@ Options
Use port number NUMBER for address 2.
-
-
+
+ --rebuild-gvmd-data=TYPES
+
+
+ Reload all gvmd data objects of a given types from feed.
+
+
+
+ The types must be "all" or a comma-separated of the
+ following: "configs", "port_lists" and
+ "report_formats".
+
+
+
--rebuild-scap
diff --git a/src/gvmd.c b/src/gvmd.c
index d699db061..c07733574 100644
--- a/src/gvmd.c
+++ b/src/gvmd.c
@@ -1836,6 +1836,7 @@ gvmd (int argc, char** argv)
static gchar *rc_name = NULL;
static gchar *relay_mapper = NULL;
static gboolean rebuild = FALSE;
+ static gchar *rebuild_gvmd_data = NULL;
static gboolean rebuild_scap = FALSE;
static gchar *role = NULL;
static gchar *disable = NULL;
@@ -2046,6 +2047,12 @@ gvmd (int argc, char** argv)
&rebuild,
"Remove NVT db, and rebuild it from the scanner.",
NULL },
+ { "rebuild-gvmd-data", '\0', 0, G_OPTION_ARG_STRING,
+ &rebuild_gvmd_data,
+ "Reload all gvmd data objects of a given types from feed."
+ " The types must be \"all\" or a comma-separated of the following:"
+ " \"configs\", \"port_lists\" and \"report_formats\"",
+ "" },
{ "rebuild-scap", '\0', 0, G_OPTION_ARG_NONE,
&rebuild_scap,
"Rebuild all SCAP data.",
@@ -2565,6 +2572,32 @@ gvmd (int argc, char** argv)
}
return EXIT_SUCCESS;
}
+
+ if (rebuild_gvmd_data)
+ {
+ int ret;
+ gchar *error_msg;
+
+ error_msg = NULL;
+
+ proctitle_set ("gvmd: --rebuild-gvmd-data");
+
+ if (option_lock (&lockfile_checking))
+ return EXIT_FAILURE;
+
+ ret = manage_rebuild_gvmd_data_from_feed (rebuild_gvmd_data,
+ log_config,
+ &database,
+ &error_msg);
+ log_config_free ();
+ if (ret)
+ {
+ printf ("Failed to rebuild gvmd data: %s\n", error_msg);
+ g_free (error_msg);
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;
+ }
if (rebuild_scap)
{
diff --git a/src/manage.c b/src/manage.c
index d3e169607..a401cdb9e 100644
--- a/src/manage.c
+++ b/src/manage.c
@@ -5006,14 +5006,177 @@ manage_sync (sigset_t *sigmask_current,
}
}
- if (try_gvmd_data_sync)
+ if (try_gvmd_data_sync
+ && (should_sync_configs ()
+ || should_sync_port_lists ()
+ || should_sync_report_formats ()))
{
- manage_sync_configs ();
- manage_sync_port_lists ();
- manage_sync_report_formats ();
+ if (feed_lockfile_lock (&lockfile) == 0)
+ {
+ manage_sync_configs ();
+ manage_sync_port_lists ();
+ manage_sync_report_formats ();
+
+ lockfile_unlock (&lockfile);
+ }
}
}
+/**
+ * @brief Adds a switch statement for handling the return value of a
+ * gvmd data rebuild.
+ * @param type The type as a description string, e.g. "port lists"
+ */
+#define REBUILD_SWITCH(type) \
+ switch (ret) \
+ { \
+ case 0: \
+ g_message ("Rebuilt %s from feed.", type); \
+ break; \
+ case 1: \
+ if (error_msg) \
+ *error_msg = g_strdup_printf ("No %s feed directory.", \
+ type); \
+ return -1; \
+ case 2: \
+ if (error_msg) \
+ *error_msg = g_strdup_printf ("Feed owner not set or invalid" \
+ " while rebuilding %s.", \
+ type); \
+ return -1; \
+ case 3: \
+ if (error_msg) \
+ *error_msg = g_strdup_printf ("NVTs must be available" \
+ " while rebuilding %s.", \
+ type); \
+ return -1; \
+ default: \
+ if (error_msg) \
+ *error_msg = g_strdup_printf ("Internal error" \
+ " while rebuilding %s.", \
+ type); \
+ return -1; \
+ }
+
+/**
+ * @brief Rebuild configs, port lists and report formats from feed.
+ *
+ * @param[in] types Comma-separated lists of types to rebuild or "all".
+ * @param[in] log_config Logging configuration list.
+ * @param[in] database Connection info for manage database.
+ * @param[out] error_msg Error message.
+ *
+ * @return 0 success, -1 failed.
+ */
+int
+manage_rebuild_gvmd_data_from_feed (const char *types,
+ GSList *log_config,
+ const db_conn_info_t *database,
+ gchar **error_msg)
+{
+ int ret;
+ lockfile_t lockfile;
+ gboolean sync_configs, sync_port_lists, sync_report_formats;
+
+ sync_configs = sync_port_lists = sync_report_formats = FALSE;
+
+ if (strcasecmp (types, "all") == 0)
+ {
+ sync_configs = TRUE;
+ sync_port_lists = TRUE;
+ sync_report_formats = TRUE;
+ }
+ else
+ {
+ gchar **split, **split_iter;
+ split = g_strsplit (types, ",", -1);
+
+ if (*split == NULL)
+ {
+ g_free (split);
+ if (error_msg)
+ *error_msg = g_strdup ("No types given.");
+ return -1;
+ }
+
+ split_iter = split;
+ while (*split_iter)
+ {
+ gchar *type = g_strstrip (*split_iter);
+
+ if (strcasecmp (type, "configs") == 0)
+ sync_configs = TRUE;
+ else if (strcasecmp (type, "port_lists") == 0)
+ sync_port_lists = TRUE;
+ else if (strcasecmp (type, "report_formats") == 0)
+ sync_report_formats = TRUE;
+ else
+ {
+ if (error_msg)
+ *error_msg = g_strdup_printf ("Invalid type \"%s\""
+ " (must be \"configs\","
+ " \"port_lists\","
+ " \"report_formats\""
+ " or \"all\")",
+ type);
+ g_strfreev (split);
+ return -1;
+ }
+ split_iter ++;
+ }
+ g_strfreev (split);
+ }
+
+ ret = feed_lockfile_lock_timeout (&lockfile);
+ if (ret == 1)
+ {
+ if (error_msg)
+ *error_msg = g_strdup ("Feed locked.");
+ return -1;
+ }
+ else if (ret)
+ {
+ if (error_msg)
+ *error_msg = g_strdup ("Error acquiring feed lock.");
+ return -1;
+ }
+
+ ret = manage_option_setup (log_config, database);
+ if (ret)
+ {
+ if (error_msg)
+ *error_msg = g_strdup ("Error setting up log config or"
+ " database connection.");
+ return -1;
+ }
+
+ if (sync_configs)
+ {
+ g_message ("Rebuilding configs from feed...");
+ ret = manage_rebuild_configs ();
+ REBUILD_SWITCH ("configs")
+ }
+
+ if (sync_port_lists)
+ {
+ g_message ("Rebuilding port lists from feed...");
+ ret = manage_rebuild_port_lists ();
+ REBUILD_SWITCH ("port lists")
+ }
+
+ if (sync_report_formats)
+ {
+ g_message ("Rebuilding report formats from feed...");
+ ret = manage_rebuild_report_formats ();
+ REBUILD_SWITCH ("report formats")
+ }
+
+ feed_lockfile_unlock (&lockfile);
+ return 0;
+}
+
+#undef REBUILD_SWITCH
+
/**
* @brief Schedule any actions that are due.
*
diff --git a/src/manage.h b/src/manage.h
index 6ca56faff..58edaaf26 100644
--- a/src/manage.h
+++ b/src/manage.h
@@ -2717,6 +2717,12 @@ set_scheduled_user_uuid (const gchar* uuid);
void
manage_sync (sigset_t *, int (*fork_update_nvt_cache) (), gboolean);
+int
+manage_rebuild_gvmd_data_from_feed (const char *,
+ GSList *,
+ const db_conn_info_t *,
+ gchar **);
+
int
manage_schedule (manage_connection_forker_t,
gboolean,
diff --git a/src/manage_configs.c b/src/manage_configs.c
index 520305a72..2d4ccaf63 100644
--- a/src/manage_configs.c
+++ b/src/manage_configs.c
@@ -300,17 +300,21 @@ create_config_from_file (const gchar *path)
}
/**
- * @brief Sync a single config with the feed.
+ * @brief Gets if a config must be synced a file path in the feed.
+ *
+ * @param[in] path Path to config XML in feed.
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ * @param[out] config Config row id if it already exists, 0 if config is new.
*
- * @param[in] path Path to config XML in feed.
+ * @return 1 if config should be synced, 0 otherwise
*/
-static void
-sync_config_with_feed (const gchar *path)
+static int
+should_sync_config_from_path (const char *path, gboolean rebuild,
+ config_t *config)
{
gchar **split, *full_path, *uuid;
- config_t config;
- g_debug ("%s: considering %s", __func__, path);
+ *config = 0;
split = g_regex_split_simple
(/* Full-and-Fast--daba56c8-73ec-11df-a475-002264764cea.xml */
@@ -321,68 +325,106 @@ sync_config_with_feed (const gchar *path)
{
g_strfreev (split);
g_warning ("%s: path not in required format: %s", __func__, path);
- return;
+ return 0;
}
- full_path = g_build_filename (feed_dir_configs (), path, NULL);
-
uuid = g_strdup_printf ("%s-%s-%s-%s-%s",
split[1], split[2], split[3], split[4], split[5]);
g_strfreev (split);
- if (find_config_no_acl (uuid, &config) == 0
- && config)
+ if (find_config_no_acl (uuid, config) == 0
+ && *config)
{
+ if (rebuild)
+ return 1;
+
+ full_path = g_build_filename (feed_dir_configs (), path, NULL);
+
g_free (uuid);
g_debug ("%s: considering %s for update", __func__, path);
- if (config_updated_in_feed (config, full_path))
+ if (config_updated_in_feed (*config, full_path))
{
- g_debug ("%s: updating %s", __func__, path);
- update_config_from_file (config, full_path);
+ return 1;
}
g_free (full_path);
- return;
+ return 0;
}
- if (find_trash_config_no_acl (uuid, &config) == 0
- && config)
+ if (find_trash_config_no_acl (uuid, config) == 0
+ && *config)
{
g_free (uuid);
- return;
+ *config = 0;
+ return 0;
}
g_free (uuid);
+ *config = 0;
+ return 1;
+}
- g_debug ("%s: adding %s", __func__, path);
+/**
+ * @brief Sync a single config with the feed.
+ *
+ * @param[in] path Path to config XML in feed.
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ */
+static void
+sync_config_with_feed (const gchar *path, gboolean rebuild)
+{
+ config_t config;
- create_config_from_file (full_path);
+ g_debug ("%s: considering %s", __func__, path);
- g_free (full_path);
+ if (should_sync_config_from_path (path, rebuild, &config))
+ {
+ gchar *full_path;
+ full_path = g_build_filename (feed_dir_configs (), path, NULL);
+ switch (config)
+ {
+ case 0:
+ g_debug ("%s: adding %s", __func__, path);
+ create_config_from_file (full_path);
+ break;
+ default:
+ g_debug ("%s: updating %s", __func__, path);
+ update_config_from_file (config, full_path);
+ }
+ g_free (full_path);
+ }
}
/**
- * @brief Sync all configs with the feed.
- *
- * Create configs that exists in the feed but not in the db.
- * Update configs in the db that have changed on the feed.
- * Do nothing to configs in db that have been removed from the feed.
+ * @brief Open the configs feed directory if it is available and the
+ * feed owner is set.
+ * Optionally set the current user to the feed owner on success.
+ *
+ * The sync will be skipped if the feed directory does not exist or
+ * the feed owner is not set.
+ * For configs the NVTs also have to exist.
+ *
+ * @param[out] dir The directory as GDir if available and feed owner is set,
+ * NULL otherwise.
+ * @param[in] set_current_user Whether to set current user to feed owner.
*
- * @return 0 success, -1 error.
+ * @return 0 success, 1 no feed directory, 2 no feed owner, 3 NVTs missing,
+ * -1 error.
*/
-int
-sync_configs_with_feed ()
+static int
+try_open_configs_feed_dir (GDir **dir, gboolean set_current_user)
{
+ char *feed_owner_uuid, *feed_owner_name;
GError *error;
- GDir *dir;
- const gchar *config_path;
gchar *nvt_feed_version;
-
+
+ *dir = NULL;
+
/* Test if base feed directory exists */
if (configs_feed_dir_exists () == FALSE)
- return 0;
+ return 1;
/* Only sync if NVTs are up to date. */
@@ -390,34 +432,34 @@ sync_configs_with_feed ()
if (nvt_feed_version == NULL)
{
g_debug ("%s: no NVTs so not syncing from feed", __func__);
- return 0;
+ return 3;
}
g_free (nvt_feed_version);
/* Setup owner. */
- setting_value (SETTING_UUID_FEED_IMPORT_OWNER, ¤t_credentials.uuid);
+ setting_value (SETTING_UUID_FEED_IMPORT_OWNER, &feed_owner_uuid);
- if (current_credentials.uuid == NULL
- || strlen (current_credentials.uuid) == 0)
+ if (feed_owner_uuid == NULL
+ || strlen (feed_owner_uuid) == 0)
{
/* Sync is disabled by having no "Feed Import Owner". */
g_debug ("%s: no Feed Import Owner so not syncing from feed", __func__);
- return 0;
+ return 2;
}
- current_credentials.username = user_name (current_credentials.uuid);
- if (current_credentials.username == NULL)
+ feed_owner_name = user_name (feed_owner_uuid);
+ if (feed_owner_name == NULL)
{
g_debug ("%s: unknown Feed Import Owner so not syncing from feed", __func__);
- return 0;
+ return 2;
}
/* Open feed import directory. */
error = NULL;
- dir = g_dir_open (feed_dir_configs (), 0, &error);
- if (dir == NULL)
+ *dir = g_dir_open (feed_dir_configs (), 0, &error);
+ if (*dir == NULL)
{
g_warning ("%s: Failed to open directory '%s': %s",
__func__, feed_dir_configs (), error->message);
@@ -429,13 +471,56 @@ sync_configs_with_feed ()
return -1;
}
+ if (set_current_user)
+ {
+ current_credentials.uuid = feed_owner_uuid;
+ current_credentials.username = feed_owner_name;
+ }
+ else
+ {
+ free (feed_owner_uuid);
+ free (feed_owner_name);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Sync all configs with the feed.
+ *
+ * Create configs that exists in the feed but not in the db.
+ * Update configs in the db that have changed on the feed.
+ * Do nothing to configs in db that have been removed from the feed.
+ *
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ *
+ * @return 0 success, 1 no feed directory, 2 no feed owner, 3 NVTs missing,
+ * -1 error.
+ */
+int
+sync_configs_with_feed (gboolean rebuild)
+{
+ int ret;
+ GDir *dir;
+ const gchar *config_path;
+
+ ret = try_open_configs_feed_dir (&dir, TRUE);
+ switch (ret)
+ {
+ case 0:
+ // Successfully opened directory
+ break;
+ default:
+ return ret;
+ }
+
/* Sync each file in the directory. */
while ((config_path = g_dir_read_name (dir)))
if (g_str_has_prefix (config_path, ".") == 0
&& strlen (config_path) >= (36 /* UUID */ + strlen (".xml"))
&& g_str_has_suffix (config_path, ".xml"))
- sync_config_with_feed (config_path);
+ sync_config_with_feed (config_path, rebuild);
/* Cleanup. */
@@ -465,5 +550,42 @@ configs_feed_dir_exists ()
void
manage_sync_configs ()
{
- sync_configs_with_feed ();
+ sync_configs_with_feed (FALSE);
+}
+
+/**
+ * @brief Rebuild configs from the feed.
+ *
+ * @return 0 success, 1 no feed directory, 2 no feed owner, 3 NVTs missing,
+ * -1 error.
+ */
+int
+manage_rebuild_configs ()
+{
+ return sync_configs_with_feed (TRUE);
+}
+
+/**
+ * @brief Checks if the configs should be synced with the feed.
+ *
+ * @return 1 if configs should be synced, 0 otherwise
+ */
+gboolean
+should_sync_configs ()
+{
+ GDir *dir;
+ const gchar *config_path;
+ config_t config;
+
+ if (try_open_configs_feed_dir (&dir, FALSE))
+ return FALSE;
+
+ while ((config_path = g_dir_read_name (dir)))
+ if (g_str_has_prefix (config_path, ".") == 0
+ && strlen (config_path) >= (36 /* UUID */ + strlen (".xml"))
+ && g_str_has_suffix (config_path, ".xml")
+ && should_sync_config_from_path (config_path, FALSE, &config))
+ return TRUE;
+
+ return FALSE;
}
diff --git a/src/manage_configs.h b/src/manage_configs.h
index b6f8e0800..23f3a70f6 100644
--- a/src/manage_configs.h
+++ b/src/manage_configs.h
@@ -197,4 +197,10 @@ configs_feed_dir_exists ();
void
manage_sync_configs ();
+int
+manage_rebuild_configs ();
+
+gboolean
+should_sync_configs ();
+
#endif /* not _GVMD_MANAGE_CONFIGS_H */
diff --git a/src/manage_port_lists.c b/src/manage_port_lists.c
index 2d0d7f8d8..f398d715a 100644
--- a/src/manage_port_lists.c
+++ b/src/manage_port_lists.c
@@ -235,20 +235,24 @@ update_port_list_from_file (port_list_t port_list, const gchar *path)
}
/**
- * @brief Sync a single port_list with the feed.
+ * @brief Gets if a port list must be synced to a file path in the feed.
+ *
+ * @param[in] path Path to port list XML in feed.
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ * @param[out] port_list Port list row id if it already exists, 0 if new.
*
- * @param[in] path Path to port_list XML in feed.
+ * @return 1 if port list should be synced, 0 otherwise
*/
-static void
-sync_port_list_with_feed (const gchar *path)
+static int
+should_sync_port_list_from_path (const char *path, gboolean rebuild,
+ port_list_t *port_list)
{
gchar **split, *full_path, *uuid;
- port_list_t port_list;
- g_debug ("%s: considering %s", __func__, path);
+ *port_list = 0;
split = g_regex_split_simple
- (/* All-TCP--daba56c8-73ec-11df-a475-002264764cea.xml */
+ (/* Full-and-Fast--daba56c8-73ec-11df-a475-002264764cea.xml */
"^.*([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12}).xml$",
path, 0, 0);
@@ -256,110 +260,184 @@ sync_port_list_with_feed (const gchar *path)
{
g_strfreev (split);
g_warning ("%s: path not in required format: %s", __func__, path);
- return;
+ return 0;
}
- full_path = g_build_filename (feed_dir_port_lists (), path, NULL);
-
uuid = g_strdup_printf ("%s-%s-%s-%s-%s",
split[1], split[2], split[3], split[4], split[5]);
g_strfreev (split);
- if (find_port_list_no_acl (uuid, &port_list) == 0
- && port_list)
+ if (find_port_list_no_acl (uuid, port_list) == 0
+ && *port_list)
{
+ if (rebuild)
+ return 1;
+
+ full_path = g_build_filename (feed_dir_port_lists (), path, NULL);
+
g_free (uuid);
g_debug ("%s: considering %s for update", __func__, path);
- if (port_list_updated_in_feed (port_list, full_path))
+ if (port_list_updated_in_feed (*port_list, full_path))
{
- g_debug ("%s: updating %s", __func__, path);
- update_port_list_from_file (port_list, full_path);
+ return 1;
}
g_free (full_path);
- return;
+ return 0;
}
- if (find_trash_port_list_no_acl (uuid, &port_list) == 0
- && port_list)
+ if (find_trash_port_list_no_acl (uuid, port_list) == 0
+ && *port_list)
{
g_free (uuid);
- return;
+ *port_list = 0;
+ return 0;
}
g_free (uuid);
+ *port_list = 0;
+ return 1;
+}
- g_debug ("%s: adding %s", __func__, path);
+/**
+ * @brief Sync a single port_list with the feed.
+ *
+ * @param[in] path Path to port_list XML in feed.
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ */
+static void
+sync_port_list_with_feed (const gchar *path, gboolean rebuild)
+{
+ port_list_t port_list;
- create_port_list_from_file (full_path);
+ g_debug ("%s: considering %s", __func__, path);
- g_free (full_path);
+ if (should_sync_port_list_from_path (path, rebuild, &port_list))
+ {
+ gchar *full_path;
+ full_path = g_build_filename (feed_dir_port_lists (), path, NULL);
+ switch (port_list)
+ {
+ case 0:
+ g_debug ("%s: adding %s", __func__, path);
+ create_port_list_from_file (full_path);
+ break;
+ default:
+ g_debug ("%s: updating %s", __func__, path);
+ update_port_list_from_file (port_list, full_path);
+ }
+ g_free (full_path);
+ }
}
/**
- * @brief Sync all port lists with the feed.
- *
- * Create port lists that exists in the feed but not in the db.
- * Update port lists in the db that have changed on the feed.
- * Do nothing to db port lists that have been removed from the feed.
+ * @brief Open the port lists feed directory if it is available and the
+ * feed owner is set.
+ * Optionally set the current user to the feed owner on success.
+ *
+ * The sync will be skipped if the feed directory does not exist or
+ * the feed owner is not set.
+ *
+ * @param[out] dir The directory as GDir if available and feed owner is set,
+ * NULL otherwise.
+ * @param[in] set_current_user Whether to set current user to feed owner.
*
- * @return 0 success, -1 error.
+ * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
*/
-int
-sync_port_lists_with_feed ()
+static int
+try_open_port_lists_feed_dir (GDir **dir, gboolean set_current_user)
{
+ char *feed_owner_uuid, *feed_owner_name;
GError *error;
- GDir *dir;
- const gchar *port_list_path;
/* Test if base feed directory exists */
if (port_lists_feed_dir_exists () == FALSE)
- return 0;
+ return 1;
/* Setup owner. */
- setting_value (SETTING_UUID_FEED_IMPORT_OWNER, ¤t_credentials.uuid);
+ setting_value (SETTING_UUID_FEED_IMPORT_OWNER, &feed_owner_uuid);
- if (current_credentials.uuid == NULL
- || strlen (current_credentials.uuid) == 0)
+ if (feed_owner_uuid == NULL
+ || strlen (feed_owner_uuid) == 0)
{
/* Sync is disabled by having no "Feed Import Owner". */
g_debug ("%s: no Feed Import Owner so not syncing from feed", __func__);
- return 0;
+ return 2;
}
- current_credentials.username = user_name (current_credentials.uuid);
- if (current_credentials.username == NULL)
+ feed_owner_name = user_name (feed_owner_uuid);
+ if (feed_owner_name == NULL)
{
g_debug ("%s: unknown Feed Import Owner so not syncing from feed", __func__);
- return 0;
+ return 2;
}
/* Open feed import directory. */
error = NULL;
- dir = g_dir_open (feed_dir_port_lists (), 0, &error);
- if (dir == NULL)
+ *dir = g_dir_open (feed_dir_port_lists (), 0, &error);
+ if (*dir == NULL)
{
g_warning ("%s: Failed to open directory '%s': %s",
__func__, feed_dir_port_lists (), error->message);
g_error_free (error);
- g_free (current_credentials.uuid);
- g_free (current_credentials.username);
- current_credentials.uuid = NULL;
- current_credentials.username = NULL;
+ free (feed_owner_uuid);
+ free (feed_owner_name);
return -1;
}
+ if (set_current_user)
+ {
+ current_credentials.uuid = feed_owner_uuid;
+ current_credentials.username = feed_owner_name;
+ }
+ else
+ {
+ free (feed_owner_uuid);
+ free (feed_owner_name);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Sync all port lists with the feed.
+ *
+ * Create port lists that exists in the feed but not in the db.
+ * Update port lists in the db that have changed on the feed.
+ * Do nothing to db port lists that have been removed from the feed.
+ *
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ *
+ * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
+ */
+int
+sync_port_lists_with_feed (gboolean rebuild)
+{
+ int ret;
+ GDir *dir;
+ const gchar *port_list_path;
+
+ ret = try_open_port_lists_feed_dir (&dir, TRUE);
+ switch (ret)
+ {
+ case 0:
+ // Successfully opened directory
+ break;
+ default:
+ return ret;
+ }
+
/* Sync each file in the directory. */
while ((port_list_path = g_dir_read_name (dir)))
if (g_str_has_prefix (port_list_path, ".") == 0
&& strlen (port_list_path) >= (36 /* UUID */ + strlen (".xml"))
&& g_str_has_suffix (port_list_path, ".xml"))
- sync_port_list_with_feed (port_list_path);
+ sync_port_list_with_feed (port_list_path, rebuild);
/* Cleanup. */
@@ -389,5 +467,41 @@ port_lists_feed_dir_exists ()
void
manage_sync_port_lists ()
{
- sync_port_lists_with_feed ();
+ sync_port_lists_with_feed (FALSE);
+}
+
+/**
+ * @brief Rebuild port lists from the feed.
+ *
+ * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
+ */
+int
+manage_rebuild_port_lists ()
+{
+ return sync_port_lists_with_feed (TRUE);
+}
+
+/**
+ * @brief Checks if the port lists should be synced with the feed.
+ *
+ * @return 1 if port lists should be synced, 0 otherwise
+ */
+gboolean
+should_sync_port_lists ()
+{
+ GDir *dir;
+ const gchar *port_list_path;
+ port_list_t port_list;
+
+ if (try_open_port_lists_feed_dir (&dir, FALSE))
+ return FALSE;
+
+ while ((port_list_path = g_dir_read_name (dir)))
+ if (g_str_has_prefix (port_list_path, ".") == 0
+ && strlen (port_list_path) >= (36 /* UUID */ + strlen (".xml"))
+ && g_str_has_suffix (port_list_path, ".xml")
+ && should_sync_port_list_from_path (port_list_path, FALSE, &port_list))
+ return TRUE;
+
+ return FALSE;
}
diff --git a/src/manage_port_lists.h b/src/manage_port_lists.h
index a0414020a..61b52d537 100644
--- a/src/manage_port_lists.h
+++ b/src/manage_port_lists.h
@@ -133,4 +133,10 @@ port_lists_feed_dir_exists ();
void
manage_sync_port_lists ();
+int
+manage_rebuild_port_lists ();
+
+gboolean
+should_sync_port_lists ();
+
#endif /* not _GVMD_MANAGE_PORT_LISTS_H */
diff --git a/src/manage_report_formats.c b/src/manage_report_formats.c
index acfa13ea4..22aeea5c5 100644
--- a/src/manage_report_formats.c
+++ b/src/manage_report_formats.c
@@ -594,21 +594,25 @@ create_report_format_from_file (const gchar *path)
}
/**
- * @brief Sync a single report format with the feed.
+ * @brief Gets if a report format must be synced to a file path in the feed.
+ *
+ * @param[in] path Path to report format XML in feed.
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ * @param[out] report_format Report format id if it already exists, 0 if new.
*
- * @param[in] path Path to report format XML in feed.
+ * @return 1 if report format should be synced, 0 otherwise
*/
-static void
-sync_report_format_with_feed (const gchar *path)
+static int
+should_sync_report_format_from_path (const char *path,
+ gboolean rebuild,
+ report_format_t *report_format)
{
gchar **split, *full_path, *uuid;
- report_format_t report_format;
- g_debug ("%s: considering %s", __func__, path);
+ *report_format = 0;
split = g_regex_split_simple
- (/* Format is: [AnYtHiNg]uuid.xml
- * For example: PDF--daba56c8-73ec-11df-a475-002264764cea.xml */
+ (/* Full-and-Fast--daba56c8-73ec-11df-a475-002264764cea.xml */
"^.*([0-9a-f]{8})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{4})-([0-9a-f]{12}).xml$",
path, 0, 0);
@@ -616,111 +620,185 @@ sync_report_format_with_feed (const gchar *path)
{
g_strfreev (split);
g_warning ("%s: path not in required format: %s", __func__, path);
- return;
+ return 0;
}
- full_path = g_build_filename (feed_dir_report_formats (), path, NULL);
-
uuid = g_strdup_printf ("%s-%s-%s-%s-%s",
split[1], split[2], split[3], split[4], split[5]);
g_strfreev (split);
- if (find_report_format_no_acl (uuid, &report_format) == 0
- && report_format)
+ if (find_report_format_no_acl (uuid, report_format) == 0
+ && *report_format)
{
+ if (rebuild)
+ return 1;
+
+ full_path = g_build_filename (feed_dir_report_formats (), path, NULL);
+
g_free (uuid);
g_debug ("%s: considering %s for update", __func__, path);
- if (report_format_updated_in_feed (report_format, full_path))
+ if (report_format_updated_in_feed (*report_format, full_path))
{
- g_debug ("%s: updating %s", __func__, path);
- update_report_format_from_file (report_format, full_path);
+ return 1;
}
g_free (full_path);
- return;
+ return 0;
}
- if (find_trash_report_format_no_acl (uuid, &report_format) == 0
- && report_format)
+ if (find_trash_report_format_no_acl (uuid, report_format) == 0
+ && *report_format)
{
g_free (uuid);
- return;
+ *report_format = 0;
+ return 0;
}
g_free (uuid);
+ *report_format = 0;
+ return 1;
+}
- g_debug ("%s: adding %s", __func__, path);
+/**
+ * @brief Sync a single report format with the feed.
+ *
+ * @param[in] path Path to report format XML in feed.
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ */
+static void
+sync_report_format_with_feed (const gchar *path, gboolean rebuild)
+{
+ report_format_t report_format;
- create_report_format_from_file (full_path);
+ g_debug ("%s: considering %s", __func__, path);
- g_free (full_path);
+ if (should_sync_report_format_from_path (path, rebuild, &report_format))
+ {
+ gchar *full_path;
+ full_path = g_build_filename (feed_dir_report_formats (), path, NULL);
+ switch (report_format)
+ {
+ case 0:
+ g_debug ("%s: adding %s", __func__, path);
+ create_report_format_from_file (full_path);
+ break;
+ default:
+ g_debug ("%s: updating %s", __func__, path);
+ update_report_format_from_file (report_format, full_path);
+ }
+ g_free (full_path);
+ }
}
/**
- * @brief Sync all report formats with the feed.
- *
- * Create report formats that exists in the feed but not in the db.
- * Update report formats in the db that have changed on the feed.
- * Do nothing to report formats in db that have been removed from the feed.
+ * @brief Open the report formats feed directory if it is available and the
+ * feed owner is set.
+ * Optionally set the current user to the feed owner on success.
+ *
+ * The sync will be skipped if the feed directory does not exist or
+ * the feed owner is not set.
+ *
+ * @param[out] dir The directory as GDir if available and feed owner is set,
+ * NULL otherwise.
+ * @param[in] set_current_user Whether to set current user to feed owner.
*
- * @return 0 success, -1 error.
+ * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
*/
-int
-sync_report_formats_with_feed ()
+static int
+try_open_report_formats_feed_dir (GDir **dir, gboolean set_current_user)
{
+ char *feed_owner_uuid, *feed_owner_name;
GError *error;
- GDir *dir;
- const gchar *report_format_path;
/* Test if base feed directory exists */
if (report_formats_feed_dir_exists () == FALSE)
- return 0;
+ return 1;
/* Setup owner. */
- setting_value (SETTING_UUID_FEED_IMPORT_OWNER, ¤t_credentials.uuid);
+ setting_value (SETTING_UUID_FEED_IMPORT_OWNER, &feed_owner_uuid);
- if (current_credentials.uuid == NULL
- || strlen (current_credentials.uuid) == 0)
+ if (feed_owner_uuid == NULL
+ || strlen (feed_owner_uuid) == 0)
{
/* Sync is disabled by having no "Feed Import Owner". */
g_debug ("%s: no Feed Import Owner so not syncing from feed", __func__);
- return 0;
+ return 2;
}
- current_credentials.username = user_name (current_credentials.uuid);
- if (current_credentials.username == NULL)
+ feed_owner_name = user_name (feed_owner_uuid);
+ if (feed_owner_name == NULL)
{
g_debug ("%s: unknown Feed Import Owner so not syncing from feed",
__func__);
- return 0;
+ return 2;
}
/* Open feed import directory. */
error = NULL;
- dir = g_dir_open (feed_dir_report_formats (), 0, &error);
- if (dir == NULL)
+ *dir = g_dir_open (feed_dir_report_formats (), 0, &error);
+ if (*dir == NULL)
{
g_warning ("%s: Failed to open directory '%s': %s",
__func__, feed_dir_report_formats (), error->message);
g_error_free (error);
- g_free (current_credentials.uuid);
- g_free (current_credentials.username);
- current_credentials.uuid = NULL;
- current_credentials.username = NULL;
+ free (feed_owner_uuid);
+ free (feed_owner_name);
return -1;
}
+ if (set_current_user)
+ {
+ current_credentials.uuid = feed_owner_uuid;
+ current_credentials.username = feed_owner_name;
+ }
+ else
+ {
+ free (feed_owner_uuid);
+ free (feed_owner_name);
+ }
+
+ return 0;
+}
+
+/**
+ * @brief Sync all report formats with the feed.
+ *
+ * Create report formats that exists in the feed but not in the db.
+ * Update report formats in the db that have changed on the feed.
+ * Do nothing to report formats in db that have been removed from the feed.
+ *
+ * @param[in] rebuild Whether ignore timestamps to force a rebuild.
+ *
+ * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
+ */
+int
+sync_report_formats_with_feed (gboolean rebuild)
+{
+ int ret;
+ GDir *dir;
+ const gchar *report_format_path;
+
+ ret = try_open_report_formats_feed_dir (&dir, TRUE);
+ switch (ret)
+ {
+ case 0:
+ // Successfully opened directory
+ break;
+ default:
+ return ret;
+ }
+
/* Sync each file in the directory. */
while ((report_format_path = g_dir_read_name (dir)))
if (g_str_has_prefix (report_format_path, ".") == 0
&& strlen (report_format_path) >= (36 /* UUID */ + strlen (".xml"))
&& g_str_has_suffix (report_format_path, ".xml"))
- sync_report_format_with_feed (report_format_path);
+ sync_report_format_with_feed (report_format_path, rebuild);
/* Cleanup. */
@@ -750,5 +828,43 @@ report_formats_feed_dir_exists ()
void
manage_sync_report_formats ()
{
- sync_report_formats_with_feed ();
+ sync_report_formats_with_feed (FALSE);
+}
+
+/**
+ * @brief Rebuild port lists from the feed.
+ *
+ * @return 0 success, 1 no feed directory, 2 no feed owner, -1 error.
+ */
+int
+manage_rebuild_report_formats ()
+{
+ return sync_report_formats_with_feed (TRUE);
}
+
+/**
+ * @brief Checks if the report formats should be synced with the feed.
+ *
+ * @return 1 if report formats should be synced, 0 otherwise
+ */
+gboolean
+should_sync_report_formats ()
+{
+ GDir *dir;
+ const gchar *report_format_path;
+ report_format_t report_format;
+
+ if (try_open_report_formats_feed_dir (&dir, FALSE))
+ return FALSE;
+
+ while ((report_format_path = g_dir_read_name (dir)))
+ if (g_str_has_prefix (report_format_path, ".") == 0
+ && strlen (report_format_path) >= (36 /* UUID */ + strlen (".xml"))
+ && g_str_has_suffix (report_format_path, ".xml")
+ && should_sync_report_format_from_path (report_format_path,
+ FALSE,
+ &report_format))
+ return TRUE;
+
+ return FALSE;
+}
\ No newline at end of file
diff --git a/src/manage_report_formats.h b/src/manage_report_formats.h
index 2e0e2dde7..beba82b5b 100644
--- a/src/manage_report_formats.h
+++ b/src/manage_report_formats.h
@@ -234,4 +234,10 @@ report_formats_feed_dir_exists ();
void
manage_sync_report_formats ();
+int
+manage_rebuild_report_formats ();
+
+gboolean
+should_sync_report_formats ();
+
#endif /* not _GVMD_MANAGE_REPORT_FORMATS_H */
diff --git a/src/manage_sql_configs.c b/src/manage_sql_configs.c
index 8689bb2f2..c1d5d1469 100644
--- a/src/manage_sql_configs.c
+++ b/src/manage_sql_configs.c
@@ -48,7 +48,7 @@
/* Static headers for internal non-SQL functions. */
int
-sync_configs_with_feed ();
+sync_configs_with_feed (gboolean);
/* Static headers. */
@@ -4936,7 +4936,7 @@ check_db_configs ()
{
migrate_predefined_configs ();
- if (sync_configs_with_feed ())
+ if (sync_configs_with_feed (FALSE) <= -1)
g_warning ("%s: Failed to sync configs with feed", __func__);
/* Warn about feed resources in the trash. */
diff --git a/src/manage_sql_port_lists.c b/src/manage_sql_port_lists.c
index 42dee462e..b0ea1cad3 100644
--- a/src/manage_sql_port_lists.c
+++ b/src/manage_sql_port_lists.c
@@ -45,7 +45,7 @@
/* Static headers for internal non-SQL functions. */
int
-sync_port_lists_with_feed ();
+sync_port_lists_with_feed (gboolean);
/* Port list functions. */
@@ -2596,7 +2596,7 @@ check_db_port_lists ()
{
migrate_predefined_port_lists ();
- if (sync_port_lists_with_feed ())
+ if (sync_port_lists_with_feed (FALSE) <= -1)
g_warning ("%s: Failed to sync port lists with feed", __func__);
/*
diff --git a/src/manage_sql_report_formats.c b/src/manage_sql_report_formats.c
index 58f9cd656..b45acbae7 100644
--- a/src/manage_sql_report_formats.c
+++ b/src/manage_sql_report_formats.c
@@ -59,7 +59,7 @@
/* Non-SQL internals defined in manage_report_formats.c. */
int
-sync_report_formats_with_feed ();
+sync_report_formats_with_feed (gboolean);
/* Static headers. */
@@ -4553,7 +4553,7 @@ check_db_report_formats ()
if (migrate_predefined_report_formats ())
return -1;
- if (sync_report_formats_with_feed ())
+ if (sync_report_formats_with_feed (FALSE) <= -1)
g_warning ("%s: Failed to sync report formats with feed", __func__);
if (check_db_trash_report_formats ())