]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Changes to Common source files not applicable to open-vm-tools.
authorJohn Wolfe <jwolfe@vmware.com>
Fri, 11 Sep 2020 19:11:06 +0000 (12:11 -0700)
committerJohn Wolfe <jwolfe@vmware.com>
Fri, 11 Sep 2020 19:11:06 +0000 (12:11 -0700)
open-vm-tools/lib/include/vmware/tools/plugin.h
open-vm-tools/lib/include/vmware/tools/utils.h
open-vm-tools/libvmtools/vmtoolsConfig.c
open-vm-tools/services/vmtoolsd/mainLoop.c
open-vm-tools/services/vmtoolsd/toolsCoreInt.h

index 48d2f36b43d266bcfdb350e741b7e26a70fe80c6..1776a6260551d87731f89aae881ac4159b7933bf 100644 (file)
@@ -217,6 +217,15 @@ ToolsCore_LogState(guint level,
  */
 #define TOOLS_CORE_SIG_SERVICE_CONTROL  "tcs_service_control"
 
+/**
+ * Signal sent when a new version of global configuration is downloaded.
+ *
+ * @param[in]  src      The source object.
+ * @param[in]  ctx      ToolsAppCtx *: The application context.
+ * @param[in]  data     Client data.
+ */
+#define TOOLS_CORE_SIG_GLOBALCONF_UPDATE "tcs_globalconf_update"
+
 #endif
 
 /**
index cfa35019bce4c91aa2ae9b3c83e976a65ec53f6a..cd8ca14e049c61c29efa1a1cd5c79d9fd3eb4644 100644 (file)
@@ -105,6 +105,10 @@ VMTools_LoadConfig(const gchar *path,
                    GKeyFile **config,
                    time_t *mtime);
 
+gboolean
+VMTools_AddConfig(GKeyFile *srcConfig,
+                  GKeyFile *dstConfig);
+
 gboolean
 VMTools_WriteConfig(const gchar *path,
                     GKeyFile *config,
index c38fd312d5205c2dd1f6beb1dc248569d9aee91c..47f20b86173105e0254c08b392d5b93afe12449c 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 2008-2019 VMware, Inc. All rights reserved.
+ * Copyright (C) 2008-2020 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -175,6 +175,87 @@ exit:
 }
 
 
+/**
+ * Copies the key/value pairs from one config dictionary to another config
+ * dictionary. The key/value pairs are added only if they are not
+ * already present in the destination configuration dictionary.
+ *
+ * @param[in]     srcConfig     Configuration dictionary from which the
+ *                              key/value pairs should be added.
+ * @param[in]     dstConfig     Configuration dictionary to which the
+ *                              key/value pairs should be added..
+ *
+ * @return Whether any key/value pairs have been added to the config
+ *         dictionary.
+ */
+
+gboolean
+VMTools_AddConfig(GKeyFile *srcConfig,
+                  GKeyFile *dstConfig)
+{
+   gsize numGroups;
+   gchar **groupNames;
+   gsize i;
+   gboolean configAdded = FALSE;
+
+   g_return_val_if_fail(srcConfig != NULL, configAdded);
+   g_return_val_if_fail(dstConfig != NULL, configAdded);
+
+   groupNames = g_key_file_get_groups(srcConfig, &numGroups);
+
+   g_debug("%s: Found %d groups in config.\n", __FUNCTION__, (int) numGroups);
+
+   for (i = 0; i < numGroups; ++i) {
+      gsize numKeys;
+      gchar **keyNames;
+      gsize j;
+      GError *gErr = NULL;
+      const gchar *group = groupNames[i];
+
+      keyNames = g_key_file_get_keys(srcConfig, group, &numKeys, &gErr);
+      if (gErr != NULL) {
+         g_warning("%s: g_key_file_get_keys(%s) failed: %s\n",
+                   __FUNCTION__, group, gErr->message);
+         g_clear_error(&gErr);
+         continue;
+      }
+
+      g_debug("%s: Found %d keys for group: '%s' in config.\n",
+              __FUNCTION__, (int) numKeys, group);
+
+      for (j = 0; j < numKeys; ++j) {
+         const gchar* key = keyNames[j];
+
+         if (!g_key_file_has_key(dstConfig, group, key, NULL)) {
+            gchar *value = g_key_file_get_value(srcConfig, group, key, &gErr);
+
+            if (value == NULL && gErr != NULL) {
+               g_warning("%s: g_key_file_get_value(%s:%s) failed: %s\n",
+                         __FUNCTION__, group, key, gErr->message);
+               g_clear_error(&gErr);
+               continue;
+            }
+
+            g_key_file_set_value(dstConfig, group, key, value);
+            g_debug("%s: Added (%s:%s) to the new config\n",
+                    __FUNCTION__, group, key);
+            configAdded = TRUE;
+            g_free(value);
+         } else {
+            g_debug("%s: Ignoring (%s:%s)\n", __FUNCTION__, group, key);
+         }
+      }
+
+      g_strfreev(keyNames);
+   }
+
+   g_debug("%s: Added the config. Return val: %d\n", __FUNCTION__, configAdded);
+
+   g_strfreev(groupNames);
+   return configAdded;
+}
+
+
 /**
  * Saves the given config data to the given path.
  *
index 3a67a085e44ff9ec0fde381afd0e54bb2ba2d711..3c6313adfcdc1345d905e64f647db008b3068dcb 100644 (file)
@@ -47,6 +47,7 @@
 #if defined(_WIN32)
 #  include "codeset.h"
 #  include "guestStoreClient.h"
+#  include "globalConfig.h"
 #  include "windowsu.h"
 #else
 #  include "posix.h"
 
 #define CONFNAME_MAX_CHANNEL_ATTEMPTS "maxChannelAttempts"
 
+#if defined(_WIN32)
+/*
+ * The state of the global conf module.
+ */
+static gGlobalConfEnabled = FALSE;
+#endif
+
 
 /*
  ******************************************************************************
@@ -190,6 +198,28 @@ ToolsCoreConfFileCb(gpointer clientData)
 }
 
 
+#if defined(_WIN32)
+/**
+ * Callback TOOLS_CORE_SIG_GLOBALCONF_UPDATE signal. The signal is
+ * triggered whenever a new global configuration is downloaded.
+ *
+ * @param[in]  src   The source object.
+ * @param[in]  ctx   The ToolsAppCtx for passing config.
+ * @param[in]  state Service state.
+ */
+
+static void
+ToolsCoreGlobalConfUpdateSignalCb(gpointer src,
+                                  ToolsAppCtx *ctx,
+                                  ToolsServiceState *state)
+{
+   g_debug("%s: global config is updated. Reloading the config.", __FUNCTION__);
+
+   ToolsCore_ReloadConfigEx(state, FALSE, TRUE);
+}
+#endif
+
+
 /**
  * IO freeze signal handler. Disables the conf file check task if I/O is
  * frozen, re-enable it otherwise. See bug 529653.
@@ -481,9 +511,32 @@ ToolsCoreRunLoop(ToolsServiceState *state)
       /*
        * For now exclude the MAC due to limited testing.
        */
-      if (state->mainService && ToolsCoreHangDetector_Start(&state->ctx)) {
-         g_info("Successfully started tools hang detector");
+      if (state->mainService) {
+         if (ToolsCoreHangDetector_Start(&state->ctx)) {
+            g_info("%s: Successfully started tools hang detector",
+                   __FUNCTION__);
+         }
+#if defined(_WIN32)
+         if (GlobalConfig_Start(&state->ctx)) {
+            g_info("%s: Successfully started global config module.",
+                   __FUNCTION__);
+            if (g_signal_lookup(TOOLS_CORE_SIG_GLOBALCONF_UPDATE,
+                                G_OBJECT_TYPE(state->ctx.serviceObj)) != 0) {
+               g_signal_connect(state->ctx.serviceObj,
+                                TOOLS_CORE_SIG_GLOBALCONF_UPDATE,
+                                G_CALLBACK(ToolsCoreGlobalConfUpdateSignalCb),
+                                state);
+               g_debug("%s: Registered the handler for the "
+                       "global config update signal.", __FUNCTION__);
+               gGlobalConfEnabled = TRUE;
+            } else {
+               g_debug("%s: Failed to register the handler for the "
+                       "global config update signal", __FUNCTION__);
+            }
+         }
+#endif
       }
+
       g_main_loop_run(state->ctx.mainLoop);
 #endif
    }
@@ -616,19 +669,37 @@ ToolsCore_GetTcloName(ToolsServiceState *state)
  *
  * @param[in]  state       Service state.
  * @param[in]  reset       Whether to reset the logging subsystem.
+ * @param[in]  force       If TRUE, the config file will be loaded even if it
+ *                         has not been modified since the last check.
  */
 
 void
-ToolsCore_ReloadConfig(ToolsServiceState *state,
-                       gboolean reset)
+ToolsCore_ReloadConfigEx(ToolsServiceState *state,
+                         gboolean reset,
+                         gboolean force)
 {
    gboolean first = state->ctx.config == NULL;
    gboolean loaded;
 
+   if (force) {
+      /*
+       * Set the configMtime to 0 so that the config file from the file system
+       * is reloaded. Else, the config is loaded only if it's been modified
+       * since the last check.
+       */
+      state->configMtime = 0;
+   }
+
    loaded = VMTools_LoadConfig(state->configFile,
                                G_KEY_FILE_NONE,
                                &state->ctx.config,
                                &state->configMtime);
+#if defined(_WIN32)
+   if (gGlobalConfEnabled && (loaded || force)) {
+      gboolean globalConfigUpdated =  GlobalConfig_Update(state->ctx.config);
+      loaded = loaded || globalConfigUpdated;
+   }
+#endif
 
    if (!first && loaded) {
       g_debug("Config file reloaded.\n");
@@ -664,6 +735,24 @@ ToolsCore_ReloadConfig(ToolsServiceState *state,
 }
 
 
+/**
+ * Reloads the config file and re-configure the logging subsystem if the
+ * log file was updated. If the config file is being loaded for the first
+ * time, try to upgrade it to the new version if an old version is
+ * detected.
+ *
+ * @param[in]  state       Service state.
+ * @param[in]  reset       Whether to reset the logging subsystem.
+ */
+
+void
+ToolsCore_ReloadConfig(ToolsServiceState *state,
+                       gboolean reset)
+{
+   ToolsCore_ReloadConfigEx(state, reset, FALSE);
+}
+
+
 #if defined(_WIN32)
 
 /**
index 06c99020294d6d35916b8d9e431acfbd6a225d31..6b9f38a292a1a19d233093e9bc82cd975b8042ee 100644 (file)
@@ -143,6 +143,11 @@ void
 ToolsCore_ReloadConfig(ToolsServiceState *state,
                        gboolean reset);
 
+void
+ToolsCore_ReloadConfigEx(ToolsServiceState *state,
+                         gboolean reset,
+                         gboolean force);
+
 void
 ToolsCore_RegisterPlugins(ToolsServiceState *state);