]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Clean up the Tools Core "utils" API.
authorVMware, Inc <>
Tue, 17 Nov 2009 22:11:10 +0000 (14:11 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Tue, 17 Nov 2009 22:11:10 +0000 (14:11 -0800)
Get rid of a bunch of functions that were either sort of redundant or
not really needed at all. Now an app that needs to use the vmtools.dll
logging just needs to call two functions:

VMTools_LoadConfig() (or load the config data some other way)
VMTools_ConfigLogging()

And those same functions provide all the functionality previously offered
by the other, now defunt, functions.

Change all call sites to use the new functions.

Also, two minor improvements to the library:
. the logging subsystem is not activated by default when a process loads
the library. This makes it opt-in (users have to explicitly call
VMTools_ConfigLogging() to enable the vmtools.dll logging code).
. the log reset code now handles keeping log files opened also for
sub-domains (previously only the default log domain would get that
treatment).

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/hgfsclient/hgfsclient.c
open-vm-tools/lib/include/vmware/tools/utils.h
open-vm-tools/libvmtools/vmtools.c
open-vm-tools/libvmtools/vmtoolsConfig.c
open-vm-tools/libvmtools/vmtoolsLog.c
open-vm-tools/services/vmtoolsd/cmdLine.c
open-vm-tools/services/vmtoolsd/mainLoop.c
open-vm-tools/services/vmtoolsd/mainPosix.c
open-vm-tools/services/vmtoolsd/toolsCoreInt.h
open-vm-tools/toolbox/toolboxInt.c
open-vm-tools/toolbox/toolboxcmd-scripts.c

index f387483bcfd1a3dcb444cf56c418dd08bc2eed61..8229c805ea9a59a9ad43402d7017a2f48cde2e60 100644 (file)
@@ -316,21 +316,15 @@ static Bool
 HgfsClient_Init(void)
 {
    Bool success = FALSE;
-   gchar *confFile;
-   GKeyFile *conf;
-
-   confFile = VMTools_GetToolsConfFile();
-   conf = VMTools_LoadConfig(confFile, G_KEY_FILE_NONE, FALSE);
+   GKeyFile *conf = NULL;
 
+   VMTools_LoadConfig(NULL, G_KEY_FILE_NONE, &conf, NULL);
+   VMTools_ConfigLogging("hgfsclient", conf, FALSE, FALSE);
    if (conf != NULL) {
-      VMTools_ConfigLogging(conf);
       g_key_file_free(conf);
       conf = NULL;
    }
 
-   g_free(confFile);
-   confFile = NULL;
-
    if (!VmCheck_IsVirtualWorld()) {
       Warning("This application must be run in a Virtual Machine.\n");
       goto out;
index f38ff851b67e8484aef9893cbba63e6009f42bba..0ea624f83e0932a4c84c4694d68f651f96570c55 100644 (file)
 /**
  * @file utils.h
  *
- *    Public functions from the VMTools shared library.
+ *    Public functions from the VMTools shared library, and other definitions.
  *
  * @addtogroup vmtools_utils
  * @{
  */
 
-#if !defined(G_LOG_DOMAIN)
-#  define G_LOG_DOMAIN VMTools_GetDefaultLogDomain()
-#endif
-
 #define  VMTOOLS_GUEST_SERVICE   "vmsvc"
 #define  VMTOOLS_USER_SERVICE    "vmusr"
 
 #  define VMTOOLS_EXTERN_C
 #endif
 
-/* Needs to come before glib.h. */
-VMTOOLS_EXTERN_C const char *
-VMTools_GetDefaultLogDomain(void);
-
 #include <glib.h>
 #if defined(G_PLATFORM_WIN32)
 #  include <windows.h>
@@ -67,7 +59,7 @@ VMTools_GetDefaultLogDomain(void);
  * Converts an UTF-8 path to the local (i.e., glib) file name encoding.
  * This is a no-op on Windows, since the local encoding is always UTF-8
  * in glib. The returned value should not be freed directly; instead,
- * use VMTOOLS_FREE_FILENAME.
+ * use VMTOOLS_RELEASE_FILENAME_LOCAL.
  *
  * @param[in]  path  Path in UTF-8 (should not be NULL).
  * @param[out] err   Where to store errors (type: GError **; may be NULL).
@@ -103,31 +95,16 @@ void
 vm_free(void *ptr);
 
 void
-VMTools_SetDefaultLogDomain(const gchar *domain);
-
-void
-VMTools_ConfigLogging(GKeyFile *cfg);
-
-void
-VMTools_EnableLogging(gboolean enable);
+VMTools_ConfigLogging(const gchar *defaultDomain,
+                      GKeyFile *cfg,
+                      gboolean force,
+                      gboolean reset);
 
-gchar *
-VMTools_GetToolsConfFile(void);
-
-GKeyFile *
+gboolean
 VMTools_LoadConfig(const gchar *path,
                    GKeyFileFlags flags,
-                   gboolean autoUpgrade);
-
-
-gboolean
-VMTools_ReloadConfig(const gchar *path,
-                     GKeyFileFlags flags,
-                     GKeyFile **config,
-                     time_t *mtime);
-
-void
-VMTools_ResetLogging(gboolean cleanDefault);
+                   GKeyFile **config,
+                   time_t *mtime);
 
 gboolean
 VMTools_WriteConfig(const gchar *path,
index 544a49188fd20a899e19ed2d3f3ad1fffc106206..021782c16ce9c0bd4406f2365424faae3007c920 100644 (file)
@@ -86,14 +86,12 @@ VMToolsDllInit(void *lib)
 #if defined(_WIN32)
    WiperInitData wiperData;
    CoreDump_SetUnhandledExceptionFilter();
-   VMTools_ResetLogging(FALSE);
    wiperData.resourceModule = lib;
    success = (NetUtil_LoadIpHlpApiDll() == ERROR_SUCCESS);
    ASSERT(success);
    success = Wiper_Init(&wiperData);
    ASSERT(success);
 #else
-   VMTools_ResetLogging(FALSE);
    success = Wiper_Init(NULL);
    ASSERT(success);
 #endif
@@ -113,7 +111,6 @@ VMToolsDllFini(void)
 #if defined(_WIN32)
    NetUtil_FreeIpHlpApiDll();
 #endif
-   VMTools_ResetLogging(TRUE);
 }
 
 
index db7b262d549cbb73a24b0e4566647634cd0164b7..9ed39fa1655e6b9733bdfd15df8e15cc64888d3e 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <glib/gstdio.h>
+
+#include "vm_assert.h"
 #include "conf.h"
-#include "file.h"
 #include "guestApp.h"
-#include "str.h"
-#include "util.h"
 
 /** Data types supported for translation. */
 typedef enum {
@@ -184,8 +183,8 @@ VMToolsConfigUpgrade(GuestApp_Dict *old,
  * @return String with the default config path (should be freed by caller).
  */
 
-gchar *
-VMTools_GetToolsConfFile(void)
+static gchar *
+VMToolsGetToolsConfFile(void)
 {
    char *confPath = GuestApp_GetConfPath();
    gchar *confFilePath;
@@ -202,7 +201,7 @@ VMTools_GetToolsConfFile(void)
       confPath = GuestApp_GetConfPath();
       ASSERT(confPath != NULL);
    }
-   confFilePath = g_strdup_printf("%s%c%s", confPath, DIRSEPC, CONF_FILE);
+   confFilePath = g_build_filename(confPath, CONF_FILE, NULL);
    free(confPath);
 
    return confFilePath;
@@ -210,38 +209,79 @@ VMTools_GetToolsConfFile(void)
 
 
 /**
- * Loads the configuration file at the given path. If an old configuration
- * file is detected, the caller can request for it to be automatically upgraded
- * to the new configuration format (the old configuration file is saved with a
+ * Loads the configuration file at the given path.
+ *
+ * If an old configuration file is detected and the current process has write
+ * permission to the file, the configuration data will automatically upgraded to
+ * the new configuration format (the old configuration file is saved with a
  * ".old" extension).
  *
- * @param[in] path         Path to the configuration file.
- * @param[in] flags        Flags for opening the file.
- * @param[in] autoUpgrade  Whether to try to upgrade old tools configuration.
+ * @param[in]     path     Path to the configuration file, or NULL for default
+ *                         Tools config file.
+ * @param[in]     flags    Flags for opening the file.
+ * @param[in,out] config   Where to store the config dictionary; when reloading
+ *                         the file, the old config object will be destroyed.
+ * @param[in,out] mtime    Last known modification time of the config file.
+ *                         When the function succeeds, will contain the new
+ *                         modification time read from the file. If NULL (or 0),
+ *                         the config dictionary is always loaded.
  *
- * @return A configuration dictionary, or NULL on error.
+ * @return Whether a new config dictionary was loaded.
  */
 
-GKeyFile *
+gboolean
 VMTools_LoadConfig(const gchar *path,
                    GKeyFileFlags flags,
-                   gboolean autoUpgrade)
+                   GKeyFile **config,
+                   time_t *mtime)
 {
    gchar *backup = NULL;
-   gchar *localPath;
+   gchar *defaultPath = NULL;
+   gchar *localPath = NULL;
+   struct stat confStat;
    GuestApp_Dict *old = NULL;
    GError *err = NULL;
-   GKeyFile *cfg;
+   GKeyFile *cfg = NULL;
 
-   cfg = g_key_file_new();
+   g_return_val_if_fail(config != NULL, FALSE);
+
+   if (path == NULL) {
+      defaultPath = VMToolsGetToolsConfFile();
+   }
 
-   localPath = VMTOOLS_GET_FILENAME_LOCAL(path, &err);
+   localPath = VMTOOLS_GET_FILENAME_LOCAL((path != NULL) ? path : defaultPath, &err);
    if (err != NULL) {
       g_warning("Error converting to local encoding: %s\n", err->message);
       goto exit;
    }
 
-   if (!File_IsFile(path) || File_GetSizeByPath(path) == 0) {
+   if (g_stat(localPath, &confStat) == -1) {
+      /*
+       * If the file doesn't exist, it's not an error. Just return an
+       * empty dictionary in that case. The mtime will be set to 0 if
+       * the caller requested it.
+       */
+      memset(&confStat, 0, sizeof confStat);
+      if (errno != ENOENT) {
+         g_warning("Failed to stat conf file: %s\n", strerror(errno));
+         goto exit;
+      } else {
+         cfg = g_key_file_new();
+         goto exit;
+      }
+   }
+
+   /* Check if we really need to load the data. */
+   if (mtime != NULL && confStat.st_mtime <= *mtime) {
+      goto exit;
+   }
+
+   /* Need to load the configuration data. */
+
+   cfg = g_key_file_new();
+
+   /* Empty file: just return an empty dictionary. */
+   if (confStat.st_size == 0) {
       goto exit;
    }
 
@@ -255,33 +295,35 @@ VMTools_LoadConfig(const gchar *path,
       goto error;
    }
 
-   /* Failed to load the config file; try to upgrade if requested. */
-   if (!autoUpgrade) {
-      goto error;
-   }
-
-   old = Conf_Load();
-   if (old == NULL) {
-      g_warning("Error loading old tools config data, bailing out.\n");
-      goto error;
-   }
+   /*
+    * Failed to load the config file; try to upgrade if requested. But only do
+    * it if the user is using the default conf file path; the old "Conf_Load()"
+    * API doesn't allow us to provide a custom config file path.
+    */
+   if (path == NULL) {
+      old = Conf_Load();
+      if (old == NULL) {
+         g_warning("Error loading old tools config data, bailing out.\n");
+         goto error;
+      }
 
-   VMToolsConfigUpgrade(old, cfg);
-   backup = g_strdup_printf("%s.old", path);
+      VMToolsConfigUpgrade(old, cfg);
+      backup = g_strdup_printf("%s.old", localPath);
 
-   if (!File_IsFile(backup)) {
-      if (!File_Rename(path, backup)) {
-         g_warning("Error creating backup of old config file.\n");
-         goto error;
+      if (!g_file_test(backup, G_FILE_TEST_IS_REGULAR)) {
+         if (g_rename(localPath, backup) == -1) {
+            g_warning("Error creating backup of old config file.\n");
+            goto error;
+         }
+      } else {
+         g_warning("Backup config exists, skipping backup.\n");
       }
-   } else {
-      g_warning("Backup config exists, skipping backup.\n");
-   }
 
-   g_clear_error(&err);
+      g_clear_error(&err);
 
-   if (!VMTools_WriteConfig(path, cfg, NULL)) {
-      goto error;
+      if (!VMTools_WriteConfig((path != NULL) ? path : defaultPath, cfg, NULL)) {
+         goto error;
+      }
    }
 
    goto exit;
@@ -295,81 +337,19 @@ exit:
    if (old != NULL) {
       GuestApp_FreeDict(old);
    }
-   g_free(backup);
-   VMTOOLS_RELEASE_FILENAME_LOCAL(localPath);
-   return cfg;
-}
-
-
-/**
- * Reloads the configuration file at the given path if it has changed since the
- * given timestamp. No translation (such as in VMTools_LoadConfig()) will be
- * performed.
- *
- * @param[in]     path     Path to the config file.
- * @param[in]     flags    Flags to use when opening the file.
- * @param[in,out] config   GKeyFile object; when reloading the file, the old
- *                         config object will be destroyed.
- * @param[in,out] mtime    Last known modification time of the config file.
- *                         When the function succeeds, will contain the new
- *                         modification time read from the file.
- *
- * @return Whether the file was reloaded.
- */
-
-gboolean
-VMTools_ReloadConfig(const gchar *path,
-                     GKeyFileFlags flags,
-                     GKeyFile **config,
-                     time_t *mtime)
-{
-   struct stat confStat;
-   gboolean ret = FALSE;
-   GKeyFile *newConfig = NULL;
-
-   ASSERT(config != NULL);
-   ASSERT(mtime != NULL);
-
-   if (g_stat(path, &confStat) == -1) {
-      g_debug("Failed to stat conf file: %s\n", strerror(errno));
-      goto exit;
-   }
-
-   if (*mtime == 0 || confStat.st_mtime > *mtime) {
-      GError *err = NULL;
-      gchar *localPath;
-
-      localPath = VMTOOLS_GET_FILENAME_LOCAL(path, &err);
-      if (err != NULL) {
-         g_warning("Error converting to local encoding: %s\n", err->message);
-         goto exit;
-      }
-
-      newConfig = g_key_file_new();
-      g_key_file_load_from_file(newConfig, localPath, flags, &err);
-
-      if (err != NULL) {
-         g_warning("Error loading conf file: %s\n", err->message);
-         g_clear_error(&err);
-         g_key_file_free(newConfig);
-         newConfig = NULL;
-      } else {
-         ret = TRUE;
-      }
-
-      VMTOOLS_RELEASE_FILENAME_LOCAL(localPath);
-   }
-
-   if (newConfig != NULL) {
+   if (cfg != NULL) {
       if (*config != NULL) {
          g_key_file_free(*config);
       }
-      *config = newConfig;
-      *mtime = confStat.st_mtime;
+      *config = cfg;
+      if (mtime != NULL) {
+         *mtime = confStat.st_mtime;
+      }
    }
-
-exit:
-   return ret;
+   g_free(backup);
+   g_free(defaultPath);
+   VMTOOLS_RELEASE_FILENAME_LOCAL(localPath);
+   return (cfg != NULL);
 }
 
 
@@ -390,14 +370,18 @@ VMTools_WriteConfig(const gchar *path,
 {
    gboolean ret = FALSE;
    gchar *data = NULL;
+   gchar *defaultPath = NULL;
    gchar *localPath = NULL;
    FILE *out = NULL;
    GError *lerr = NULL;
 
-   ASSERT(path != NULL);
    ASSERT(config != NULL);
 
-   localPath = VMTOOLS_GET_FILENAME_LOCAL(path, &lerr);
+   if (path == NULL) {
+      defaultPath = VMToolsGetToolsConfFile();
+   }
+
+   localPath = VMTOOLS_GET_FILENAME_LOCAL((path != NULL) ? path : defaultPath, &lerr);
    if (lerr != NULL) {
       g_warning("Error converting to local encoding: %s\n", lerr->message);
       goto exit;
@@ -437,6 +421,7 @@ exit:
       g_clear_error(&lerr);
    }
    g_free(data);
+   g_free(defaultPath);
    VMTOOLS_RELEASE_FILENAME_LOCAL(localPath);
    return ret;
 }
index d0821209d03e936f215cb318e48d57ec7893fd52..e44af17d6e4a158d34b844596aeeb0fe1c1dfccd 100644 (file)
 #define SHOULD_LOG(level, data) (IS_FATAL(level) || \
                                  (gLogEnabled && ((data)->mask & (level))))
 
+/** Clean up the contents of a log handler. */
+#define CLEAR_LOG_HANDLER(handler) do { \
+   if ((handler)->file != NULL) {       \
+      fclose((handler)->file);          \
+   }                                    \
+   g_free((handler)->path);             \
+   g_free((handler)->domain);           \
+} while (0)
+
 
 static void
 VMToolsLogFile(const gchar *domain,
@@ -148,13 +157,15 @@ VMToolsLogOpenFile(const gchar *path,
    ASSERT(path != NULL);
    pathLocal = VMTOOLS_GET_FILENAME_LOCAL(path, NULL);
 
-   if (!append && g_file_test(path, G_FILE_TEST_EXISTS)) {
+   if (!append && g_file_test(pathLocal, G_FILE_TEST_EXISTS)) {
       /* Back up existing log file. */
       gchar *bakFile = g_strdup_printf("%s.old", pathLocal);
       if (!g_file_test(bakFile, G_FILE_TEST_IS_DIR) &&
           (!g_file_test(bakFile, G_FILE_TEST_EXISTS) ||
            g_unlink(bakFile) == 0)) {
          g_rename(pathLocal, bakFile);
+      } else {
+         g_unlink(pathLocal);
       }
       g_free(bakFile);
    }
@@ -390,12 +401,11 @@ VMToolsLogFile(const gchar *domain,
 
 /**
  * Configures the given log domain based on the data provided in the given
- * dictionary. If the log domain being configured doesn't match the default
- * (@see VMTools_GetDefaultLogDomain()), and no specific handler is defined
- * for the domain, the handler is inherited from the default domain, instead
- * of using the default handler. This allows reusing the same log file, for
- * example, while maintaining the ability to enable different log levels
- * for different domains.
+ * dictionary. If the log domain being configured doesn't match the default, and
+ * no specific handler is defined for the domain, the handler is inherited from
+ * the default domain, instead of using the default handler. This allows reusing
+ * the same log file, for example, while maintaining the ability to enable
+ * different log levels for different domains.
  *
  * For the above to properly work, the default log domain has to be configured
  * before any other domains.
@@ -441,7 +451,7 @@ VMToolsConfigLogDomain(const gchar *domain,
    handler = g_key_file_get_string(cfg, LOGGING_GROUP, key, NULL);
 
    if (handler == NULL) {
-      if (strcmp(domain, VMTools_GetDefaultLogDomain()) == 0) {
+      if (strcmp(domain, gLogDomain) == 0) {
          handlerFn = DEFAULT_HANDLER;
       } else {
          handlerFn = gDefaultLogFunc;
@@ -538,7 +548,7 @@ VMToolsConfigLogDomain(const gchar *domain,
    data->append = (handler != NULL && strcmp(handler, "file+") == 0);
    logpath = NULL;
 
-   if (strcmp(domain, VMTools_GetDefaultLogDomain()) == 0) {
+   if (strcmp(domain, gLogDomain) == 0) {
       /*
        * Replace the global log configuration. If the default log domain was
        * logging to a file and the file path hasn't changed, then keep the old
@@ -546,7 +556,7 @@ VMToolsConfigLogDomain(const gchar *domain,
        */
       LogHandlerData *old = gDefaultData;
 
-      if (old->file != NULL) {
+      if (old != NULL && old->file != NULL) {
          ASSERT(old->path);
          if (data->path != NULL && strcmp(data->path, old->path) == 0) {
             g_free(data->path);
@@ -574,7 +584,7 @@ VMToolsConfigLogDomain(const gchar *domain,
          gDomains = g_ptr_array_new();
       }
       g_ptr_array_add(gDomains, data);
-      data->handlerId = g_log_set_handler(domain, 
+      data->handlerId = g_log_set_handler(domain,
                                           G_LOG_LEVEL_MASK |
                                           G_LOG_FLAG_FATAL |
                                           G_LOG_FLAG_RECURSION,
@@ -588,63 +598,187 @@ exit:
 }
 
 
-/* Public API. */
-
 /**
- * Returns the default log domain for the application.
+ * Resets the vmtools logging subsystem, freeing up data and restoring the
+ * original glib configuration.
  *
- * @return  A string with the name of the log domain.
+ * @param[in]  hard     Whether to do a "hard" reset of the logging system
+ *                      (cleaning up any log domain existing state and freeing
+ *                      associated memory).
  */
 
-const char *
-VMTools_GetDefaultLogDomain(void)
+static void
+VMToolsResetLogging(gboolean hard)
 {
-   return gLogDomain;
+   gLogEnabled = FALSE;
+   g_log_set_default_handler(g_log_default_handler, NULL);
+
+   if (gDomains != NULL) {
+      guint i;
+      for (i = 0; i < gDomains->len; i++) {
+         LogHandlerData *data = g_ptr_array_index(gDomains, i);
+         g_log_remove_handler(data->domain, data->handlerId);
+         if (hard) {
+            CLEAR_LOG_HANDLER(data);
+            g_free(data);
+         }
+      }
+      if (hard) {
+         g_ptr_array_free(gDomains, TRUE);
+         gDomains = NULL;
+      }
+   }
+
+   if (hard && gDefaultData != NULL) {
+      CLEAR_LOG_HANDLER(gDefaultData);
+      g_free(gDefaultData);
+      gDefaultData = NULL;
+   }
+
+   if (gLogDomain != NULL) {
+      g_free(gLogDomain);
+      gLogDomain = NULL;
+   }
+
+   gDefaultLogFunc = DEFAULT_HANDLER;
 }
 
 
 /**
- * Sets the default log domain. This only changes the output of the default
- * log handler.
+ * Restores the logging configuration in the given config data. This means doing
+ * the following:
+ *
+ * . if the old log domain exists in the current configuration, and in case both
+ *   the old and new configuration used log files, then re-use the file that was
+ *   already opened.
+ * . if they don't use the same configuration, close the log file for the old
+ *   configuration.
+ * . if an old log domain doesn't exist in the new configuration, then
+ *   release any resources the old configuration was using for that domain.
  *
- * @param[in]  domain   The log domain.
+ * @param[in] oldDefault    Data for the old default domain.
+ * @param[in] oldDomains    List of old log domains.
  */
 
-void
-VMTools_SetDefaultLogDomain(const gchar *domain)
+static void
+VMToolsRestoreLogging(LogHandlerData *oldDefault,
+                      GPtrArray *oldDomains)
 {
-   ASSERT(domain != NULL);
-   if (gLogDomain != NULL) {
-      g_free(gLogDomain);
+   /* First, restore what needs to be restored. */
+   if (gDomains != NULL && oldDomains != NULL) {
+      guint i;
+      for (i = 0; i < gDomains->len; i++) {
+         guint j;
+         LogHandlerData *data = g_ptr_array_index(gDomains, i);
+
+         /* Try to find the matching old config. */
+         for (j = 0; j < oldDomains->len; j++) {
+            LogHandlerData *olddata = g_ptr_array_index(oldDomains, j);
+            if (strcmp(data->domain, olddata->domain) == 0) {
+               if (data->path != NULL && olddata->file != NULL) {
+                  ASSERT(data->file == NULL);
+                  data->file = olddata->file;
+                  olddata->file = NULL;
+               }
+               break;
+            }
+         }
+      }
+   }
+
+   if (gDefaultData != NULL && oldDefault != NULL) {
+      if (gDefaultData->path != NULL && oldDefault->file != NULL) {
+         ASSERT(gDefaultData->file == NULL);
+         gDefaultData->file = oldDefault->file;
+         oldDefault->file = NULL;
+      }
+   }
+
+   /* Second, clean up the old configuration data. */
+   if (oldDomains != NULL) {
+      while (oldDomains->len > 0) {
+         LogHandlerData *data = g_ptr_array_remove_index_fast(oldDomains,
+                                                              oldDomains->len - 1);
+         CLEAR_LOG_HANDLER(data);
+         g_free(data);
+      }
+   }
+
+   if (oldDefault != NULL) {
+      CLEAR_LOG_HANDLER(oldDefault);
    }
-   gLogDomain = g_strdup(domain);
 }
 
 
+/* Public API. */
+
 /**
- * Configures the logging system according to the configuration provided from
- * the given dictionary.
+ * Configures the logging system according to the configuration in the given
+ * dictionary.
  *
- * @param[in] cfg    The configuration data.
+ * Optionally, it's possible to reset the logging subsystem; this will shut
+ * down all log handlers managed by the vmtools library before configuring
+ * the log system, which means that logging will behave as if the application
+ * was just started. A visible side-effect of this is that log files may be
+ * rotated (if they're not configure for appending).
+ *
+ * @param[in] defaultDomain   Name of the default log domain.
+ * @param[in] cfg             The configuration data. May be NULL.
+ * @param[in] force           Whether to force logging to be enabled.
+ * @param[in] reset           Whether to reset the logging subsystem first.
  */
 
 void
-VMTools_ConfigLogging(GKeyFile *cfg)
+VMTools_ConfigLogging(const gchar *defaultDomain,
+                      GKeyFile *cfg,
+                      gboolean force,
+                      gboolean reset)
 {
    gchar **list;
    gchar **curr;
+   GPtrArray *oldDomains = NULL;
+   LogHandlerData *oldDefault = NULL;
 
-   VMTools_ResetLogging(FALSE);
+   g_return_if_fail(defaultDomain != NULL);
 
-   if (!g_key_file_has_group(cfg, LOGGING_GROUP)) {
-      return;
+   /*
+    * If not resetting the logging system, keep the old domains around. After
+    * we're done loading the new configuration, we'll go through the old domains
+    * and restore any data that needs restoring, and clean up anything else.
+    */
+   VMToolsResetLogging(reset);
+   if (!reset) {
+      oldDefault = gDefaultData;
+      oldDomains = gDomains;
+      gDomains = NULL;
+      gDefaultData = NULL;
+   }
+
+   gLogDomain = g_strdup(defaultDomain);
+
+   /*
+    * If no logging config data exists, then we install a default log handler,
+    * just so we override the default glib one, since the caller has asked us to
+    * enable our logging system.
+    */
+   if (cfg == NULL || !g_key_file_has_group(cfg, LOGGING_GROUP)) {
+      gDefaultData = g_malloc0(sizeof *gDefaultData);
+      gDefaultData->domain = g_strdup(defaultDomain);
+      gDefaultData->mask = G_LOG_LEVEL_ERROR |
+                           G_LOG_LEVEL_CRITICAL |
+                           G_LOG_LEVEL_WARNING;
+#if defined(VMX86_DEBUG)
+      gDefaultData->mask |= G_LOG_LEVEL_MESSAGE;
+#endif
+      g_log_set_default_handler(gDefaultLogFunc, gDefaultData);
+      goto exit;
    }
 
    /*
     * Configure the default domain first. See function documentation for
     * VMToolsConfigLogDomain() for the reason.
     */
-   VMToolsConfigLogDomain(VMTools_GetDefaultLogDomain(), cfg);
+   VMToolsConfigLogDomain(gLogDomain, cfg);
 
    list = g_key_file_get_keys(cfg, LOGGING_GROUP, NULL, NULL);
 
@@ -660,7 +794,7 @@ VMTools_ConfigLogging(GKeyFile *cfg)
       domain[strlen(domain) - 6] = '\0';
 
       /* Skip the default domain. */
-      if (strcmp(domain, VMTools_GetDefaultLogDomain()) == 0) {
+      if (strcmp(domain, gLogDomain) == 0) {
          continue;
       }
 
@@ -674,97 +808,18 @@ VMTools_ConfigLogging(GKeyFile *cfg)
       gEnableCoreDump = g_key_file_get_boolean(cfg, LOGGING_GROUP,
                                                "enableCoreDump", NULL);
    }
-}
-
-
-/**
- * Enables of disables all the log domains configured by the vmtools library.
- * This doesn't affect other log domains that may have configured by other
- * code.
- *
- * @param[in] enable    Whether logging should be enabled.
- */
 
-void
-VMTools_EnableLogging(gboolean enable)
-{
-   gLogEnabled = enable;
-}
-
-
-/**
- * Resets the vmtools logging subsystem, freeing up data and optionally
- * restoring the original glib configuration.
- *
- * @param[in]  cleanDefault   Whether to clean up the default handler and
- *                            restore the original glib handler.
- */
-
-void
-VMTools_ResetLogging(gboolean cleanDefault)
-{
-   gboolean oldLogEnabled = gLogEnabled;
-   gchar *currentPath = NULL;
-   FILE *currentFile = NULL;
-
-   /* Disable logging while we're playing with the configuration. */
-   gLogEnabled = FALSE;
-
-   if (cleanDefault) {
-      g_log_set_default_handler(g_log_default_handler, NULL);
-   }
-
-   if (gDomains != NULL) {
-      guint i;
-      for (i = 0; i < gDomains->len; i++) {
-         LogHandlerData *data = g_ptr_array_index(gDomains, i);
-         g_log_remove_handler(data->domain, data->handlerId);
-         if (data->file != NULL) {
-            fclose(data->file);
-         }
-         g_free(data->path);
-         g_free(data->domain);
-         g_free(data);
+exit:
+   /* If needed, restore the old configuration. */
+   if (!reset) {
+      VMToolsRestoreLogging(oldDefault, oldDomains);
+      g_free(oldDefault);
+      if (oldDomains != NULL) {
+         g_ptr_array_free(oldDomains, TRUE);
       }
-      g_ptr_array_free(gDomains, TRUE);
-      gDomains = NULL;
-   }
-
-   if (gDefaultData != NULL) {
-      currentFile = gDefaultData->file;
-      currentPath = gDefaultData->path;
-      g_free(gDefaultData);
-      gDefaultData = NULL;
-   }
-
-   if (cleanDefault && gLogDomain != NULL) {
-      g_free(gLogDomain);
-      gLogDomain = NULL;
    }
 
-   gDefaultLogFunc = DEFAULT_HANDLER;
-
-   if (!cleanDefault) {
-      if (gLogDomain == NULL) {
-         gLogDomain = g_strdup("vmtools");
-      }
-      gDefaultData = g_malloc0(sizeof *gDefaultData);
-      gDefaultData->mask = G_LOG_LEVEL_ERROR |
-                           G_LOG_LEVEL_CRITICAL |
-                           G_LOG_LEVEL_WARNING;
-#if defined(VMX86_DEBUG)
-      gDefaultData->mask |= G_LOG_LEVEL_MESSAGE;
-#endif
-      gDefaultData->file = currentFile;
-      gDefaultData->path = currentPath;
-      gLogEnabled = oldLogEnabled;
-      g_log_set_default_handler(gDefaultLogFunc, gDefaultData);
-   } else {
-      if (currentFile != NULL) {
-         fclose(currentFile);
-      }
-      g_free(currentPath);
-   }
+   gLogEnabled |= force;
 }
 
 
index 13b13574696bc3be5bcc5c382a092a343369c4f5..608634f691272e65911a63b1c54a6a57864c4c86 100644 (file)
@@ -235,7 +235,6 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state,
       exit(0);
    }
 
-   VMTools_EnableLogging(state->log);
    if (state->name == NULL) {
       state->name = VMTOOLS_GUEST_SERVICE;
       state->mainService = TRUE;
@@ -247,6 +246,11 @@ ToolsCore_ParseCommandLine(ToolsServiceState *state,
       state->mainService = (strcmp(state->name, VMTOOLS_GUEST_SERVICE) == 0);
    }
 
+   VMTools_ConfigLogging(state->name,
+                         NULL,
+                         state->log,
+                         FALSE);
+
 #if defined(G_PLATFORM_WIN32)
    if (kill) {
       exit(ToolsCoreSignalEvent(state->name, QUIT_EVENT_NAME_FMT) ? 0 : 1);
index 49b231b99729b292cd00b5404008f55b15945d6a..235a1183526e75b45ff6a359c86f2405f5ee561d 100644 (file)
@@ -206,55 +206,41 @@ ToolsCore_GetTcloName(ToolsServiceState *state)
  * detected.
  *
  * @param[in]  state       Service state.
- * @param[in]  force       Whether to force reconfiguration of the logging
- *                         subsystem.
+ * @param[in]  reset       Whether to reset the logging subsystem.
  */
 
 void
 ToolsCore_ReloadConfig(ToolsServiceState *state,
-                       gboolean force)
+                       gboolean reset)
 {
-   char *confFile;
-   gboolean loaded = TRUE;
+   gboolean first = state->ctx.config == NULL;
+   gboolean loaded;
 
-   VMTools_SetDefaultLogDomain(state->name);
+   loaded = VMTools_LoadConfig(state->configFile,
+                               G_KEY_FILE_NONE,
+                               &state->ctx.config,
+                               &state->configMtime);
 
-   confFile = g_strdup(state->configFile);
-   if (confFile == NULL) {
-      confFile = VMTools_GetToolsConfFile();
-   }
-
-   if (state->ctx.config == NULL) {
-      state->ctx.config = VMTools_LoadConfig(confFile,
-                                             G_KEY_FILE_NONE,
-                                             state->mainService);
-      state->configMtime = time(NULL);
-      if (state->ctx.config == NULL) {
-         /* Couldn't load the config file. Just create an empty dictionary. */
-         state->ctx.config = g_key_file_new();
-      }
-   } else if (VMTools_ReloadConfig(confFile,
-                                   G_KEY_FILE_NONE,
-                                   &state->ctx.config,
-                                   &state->configMtime)) {
+   if (!first && loaded) {
       g_debug("Config file reloaded.\n");
 
       /* Inform plugins of config file update. */
       g_signal_emit_by_name(state->ctx.serviceObj,
                             TOOLS_CORE_SIG_CONF_RELOAD,
                             &state->ctx);
-   } else {
-      loaded = FALSE;
    }
 
-   if (force || loaded) {
-      VMTools_ConfigLogging(state->ctx.config);
-      if (state->log) {
-         VMTools_EnableLogging(state->log);
-      }
+   if (state->ctx.config == NULL) {
+      /* Couldn't load the config file. Just create an empty dictionary. */
+      state->ctx.config = g_key_file_new();
    }
 
-   g_free(confFile);
+   if (reset || loaded) {
+      VMTools_ConfigLogging(state->name,
+                            state->ctx.config,
+                            state->log,
+                            reset);
+   }
 }
 
 
index 66647cd09abd60ef5384ed6f3e114c560edfa259..83833d068c257ddf82b4b4c7669c4c44b1461938 100644 (file)
@@ -59,7 +59,6 @@ static gboolean
 ToolsCoreSigHUPCb(const siginfo_t *info,
                   gpointer data)
 {
-   VMTools_ResetLogging(TRUE);
    ToolsCore_ReloadConfig(data, TRUE);
    return TRUE;
 }
index c127698aab7d60728929befeb242ae3bc9db17e6..54942bd34eb25751ee004dfbb2edf406ad85c406 100644 (file)
@@ -125,7 +125,7 @@ ToolsCore_LoadPlugins(ToolsServiceState *state);
 
 void
 ToolsCore_ReloadConfig(ToolsServiceState *state,
-                       gboolean force);
+                       gboolean reset);
 
 void
 ToolsCore_RegisterPlugins(ToolsServiceState *state);
index 889b8fa8f5953e8edcdbe929a8fd9dfbdc1b5c3c..8d19c0a02e7098e9074b02243b1a6981c5103f81 100644 (file)
@@ -106,19 +106,18 @@ Toolbox_GetScriptPath(const gchar *script)   // IN
 GKeyFile *
 Toolbox_LoadToolsConf(void)
 {
-   gchar *path = VMTools_GetToolsConfFile();
-   GKeyFile *config;
+   GKeyFile *config = NULL;
 
-   config = VMTools_LoadConfig(path,
-                               G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
-                               TRUE);
+   VMTools_LoadConfig(NULL,
+                      G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+                      &config,
+                      NULL);
 
    if (config == NULL) {
       Debug("Unable to load config file.\n");
       config = g_key_file_new();
    }
 
-   g_free(path);
    return config;
 }
 
@@ -146,18 +145,15 @@ gboolean
 Toolbox_SaveToolsConf(GKeyFile *config)   // IN
 {
    gboolean ret = FALSE;
-   gchar *path = NULL;
    GError *err = NULL;
 
-   path = VMTools_GetToolsConfFile();
-   ret = VMTools_WriteConfig(path, config, &err);
+   ret = VMTools_WriteConfig(NULL, config, &err);
 
    if (!ret) {
       Warning("Error saving conf data: %s\n", err->message);
       g_clear_error(&err);
    }
 
-   g_free(path);
    return ret;
 }
 
index ee51f424dd20f3bd7ec3ee7cf7090f06e5e36943..1e2a16d0bd482481fc3a8de1c72eb44b880b5ff3 100644 (file)
@@ -101,19 +101,17 @@ GetConfName(const char *apm) // IN: apm name.
 static GKeyFile *
 LoadConfFile(void)
 {
-   gchar *confPath;
-   GKeyFile *confDict;
+   GKeyFile *confDict = NULL;
 
-   confPath = VMTools_GetToolsConfFile();
-   confDict = VMTools_LoadConfig(confPath,
-                                 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
-                                 System_IsUserAdmin());
+   VMTools_LoadConfig(NULL,
+                      G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+                      &confDict,
+                      NULL);
 
    if (confDict == NULL) {
       confDict = g_key_file_new();
    }
 
-   g_free(confPath);
    return confDict;
 }
 
@@ -250,7 +248,6 @@ ScriptToggle(const char *apm, // IN: APM name
 {
    const char *path;
    const char *confName;
-   gchar *confPath;
    int ret = EXIT_SUCCESS;
    GKeyFile *confDict;
    GError *err = NULL;
@@ -271,15 +268,13 @@ ScriptToggle(const char *apm, // IN: APM name
    }
 
    g_key_file_set_string(confDict, "powerops", confName, path);
-   confPath = VMTools_GetToolsConfFile();
-   if (!VMTools_WriteConfig(confPath, confDict, &err)) {
+   if (!VMTools_WriteConfig(NULL, confDict, &err)) {
       fprintf(stderr, "Error writing config: %s\n", err->message);
       g_clear_error(&err);
       ret = EX_TEMPFAIL;
    }
 
    g_key_file_free(confDict);
-   g_free(confPath);
    return ret;
 }
 
@@ -358,7 +353,6 @@ Script_Set(const char *apm,   // IN: APM name
 {
    const char *confName;
    int ret = EXIT_SUCCESS;
-   gchar *confPath = NULL;
    GKeyFile *confDict = NULL;
    GError *err = NULL;
 
@@ -373,19 +367,16 @@ Script_Set(const char *apm,   // IN: APM name
       return EX_USAGE;
    }
 
-   confPath = VMTools_GetToolsConfFile();
    confDict = LoadConfFile();
-
    g_key_file_set_string(confDict, "powerops", confName, path);
 
-   if (!VMTools_WriteConfig(confPath, confDict, &err)) {
+   if (!VMTools_WriteConfig(NULL, confDict, &err)) {
       fprintf(stderr, "Error writing config: %s\n", err->message);
       g_clear_error(&err);
       ret = EX_TEMPFAIL;
    }
 
    g_key_file_free(confDict);
-   g_free(confPath);
    return ret;
 }