]> git.notmuchmail.org Git - notmuch/blobdiff - notmuch-config.c
util: Fix two corner-cases in boolean term quoting function
[notmuch] / notmuch-config.c
index 247fbe4ba1e394c0d4dc34b7142dd2c2f9da3f57..8d286538c086180ef9c88ef6a00315c95fc67fea 100644 (file)
@@ -395,39 +395,28 @@ notmuch_config_open (void *ctx,
      * the configuration file, we add some comments to help the user
      * understand what can be done. */
     if (config->is_new)
-    {
        g_key_file_set_comment (config->key_file, NULL, NULL,
                                toplevel_config_comment, NULL);
-    }
 
     if (! file_had_database_group)
-    {
        g_key_file_set_comment (config->key_file, "database", NULL,
                                database_config_comment, NULL);
-    }
 
     if (! file_had_new_group)
-    {
        g_key_file_set_comment (config->key_file, "new", NULL,
                                new_config_comment, NULL);
-    }
 
     if (! file_had_user_group)
-    {
        g_key_file_set_comment (config->key_file, "user", NULL,
                                user_config_comment, NULL);
-    }
 
     if (! file_had_maildir_group)
-    {
        g_key_file_set_comment (config->key_file, "maildir", NULL,
                                maildir_config_comment, NULL);
-    }
 
-    if (! file_had_search_group) {
+    if (! file_had_search_group)
        g_key_file_set_comment (config->key_file, "search", NULL,
                                search_config_comment, NULL);
-    }
 
     return config;
 }
@@ -455,7 +444,7 @@ int
 notmuch_config_save (notmuch_config_t *config)
 {
     size_t length;
-    char *data;
+    char *data, *filename;
     GError *error = NULL;
 
     data = g_key_file_to_data (config->key_file, &length, NULL);
@@ -464,14 +453,39 @@ notmuch_config_save (notmuch_config_t *config)
        return 1;
     }
 
-    if (! g_file_set_contents (config->filename, data, length, &error)) {
-       fprintf (stderr, "Error saving configuration to %s: %s\n",
-                config->filename, error->message);
+    /* Try not to overwrite symlinks. */
+    filename = realpath (config->filename, NULL);
+    if (! filename) {
+       if (errno == ENOENT) {
+           filename = strdup (config->filename);
+           if (! filename) {
+               fprintf (stderr, "Out of memory.\n");
+               g_free (data);
+               return 1;
+           }
+       } else {
+           fprintf (stderr, "Error canonicalizing %s: %s\n", config->filename,
+                    strerror (errno));
+           g_free (data);
+           return 1;
+       }
+    }
+
+    if (! g_file_set_contents (filename, data, length, &error)) {
+       if (strcmp (filename, config->filename) != 0) {
+           fprintf (stderr, "Error saving configuration to %s (-> %s): %s\n",
+                    config->filename, filename, error->message);
+       } else {
+           fprintf (stderr, "Error saving configuration to %s: %s\n",
+                    filename, error->message);
+       }
        g_error_free (error);
+       free (filename);
        g_free (data);
        return 1;
     }
 
+    free (filename);
     g_free (data);
     return 0;
 }
@@ -482,6 +496,32 @@ notmuch_config_is_new (notmuch_config_t *config)
     return config->is_new;
 }
 
+static const char *
+_config_get (notmuch_config_t *config, char **field,
+            const char *group, const char *key)
+{
+    /* read from config file and cache value, if not cached already */
+    if (*field == NULL) {
+       char *value;
+       value = g_key_file_get_string (config->key_file, group, key, NULL);
+       if (value) {
+           *field = talloc_strdup (config, value);
+           free (value);
+       }
+    }
+    return *field;
+}
+
+static void
+_config_set (notmuch_config_t *config, char **field,
+            const char *group, const char *key, const char *value)
+{
+    g_key_file_set_string (config->key_file, group, key, value);
+
+    /* drop the cached value */
+    talloc_free (*field);
+    *field = NULL;
+}
 
 static const char **
 _config_get_list (notmuch_config_t *config,
@@ -490,6 +530,7 @@ _config_get_list (notmuch_config_t *config,
 {
     assert(outlist);
 
+    /* read from config file and cache value, if not cached already */
     if (*outlist == NULL) {
 
        char **inlist = g_key_file_get_string_list (config->key_file,
@@ -521,6 +562,8 @@ _config_set_list (notmuch_config_t *config,
                  size_t length, const char ***config_var )
 {
     g_key_file_set_string_list (config->key_file, group, name, list, length);
+
+    /* drop the cached value */
     talloc_free (*config_var);
     *config_var = NULL;
 }
@@ -528,85 +571,40 @@ _config_set_list (notmuch_config_t *config,
 const char *
 notmuch_config_get_database_path (notmuch_config_t *config)
 {
-    char *path;
-
-    if (config->database_path == NULL) {
-       path = g_key_file_get_string (config->key_file,
-                                     "database", "path", NULL);
-       if (path) {
-           config->database_path = talloc_strdup (config, path);
-           free (path);
-       }
-    }
-
-    return config->database_path;
+    return _config_get (config, &config->database_path, "database", "path");
 }
 
 void
 notmuch_config_set_database_path (notmuch_config_t *config,
                                  const char *database_path)
 {
-    g_key_file_set_string (config->key_file,
-                          "database", "path", database_path);
-
-    talloc_free (config->database_path);
-    config->database_path = NULL;
+    _config_set (config, &config->database_path, "database", "path", database_path);
 }
 
 const char *
 notmuch_config_get_user_name (notmuch_config_t *config)
 {
-    char *name;
-
-    if (config->user_name == NULL) {
-       name = g_key_file_get_string (config->key_file,
-                                     "user", "name", NULL);
-       if (name) {
-           config->user_name = talloc_strdup (config, name);
-           free (name);
-       }
-    }
-
-    return config->user_name;
+    return _config_get (config, &config->user_name, "user", "name");
 }
 
 void
 notmuch_config_set_user_name (notmuch_config_t *config,
                              const char *user_name)
 {
-    g_key_file_set_string (config->key_file,
-                          "user", "name", user_name);
-
-    talloc_free (config->user_name);
-    config->user_name = NULL;
+    _config_set (config, &config->user_name, "user", "name", user_name);
 }
 
 const char *
 notmuch_config_get_user_primary_email (notmuch_config_t *config)
 {
-    char *email;
-
-    if (config->user_primary_email == NULL) {
-       email = g_key_file_get_string (config->key_file,
-                                      "user", "primary_email", NULL);
-       if (email) {
-           config->user_primary_email = talloc_strdup (config, email);
-           free (email);
-       }
-    }
-
-    return config->user_primary_email;
+    return _config_get (config, &config->user_primary_email, "user", "primary_email");
 }
 
 void
 notmuch_config_set_user_primary_email (notmuch_config_t *config,
                                       const char *primary_email)
 {
-    g_key_file_set_string (config->key_file,
-                          "user", "primary_email", primary_email);
-
-    talloc_free (config->user_primary_email);
-    config->user_primary_email = NULL;
+    _config_set (config, &config->user_primary_email, "user", "primary_email", primary_email);
 }
 
 const char **
@@ -690,7 +688,7 @@ _item_split (char *item, char **group, char **key)
 
     *group = item;
 
-    period = index (item, '.');
+    period = strchr (item, '.');
     if (period == NULL || *(period+1) == '\0') {
        fprintf (stderr,
                 "Invalid configuration name: %s\n"
@@ -705,14 +703,8 @@ _item_split (char *item, char **group, char **key)
 }
 
 static int
-notmuch_config_command_get (void *ctx, char *item)
+notmuch_config_command_get (notmuch_config_t *config, char *item)
 {
-    notmuch_config_t *config;
-
-    config = notmuch_config_open (ctx, NULL, FALSE);
-    if (config == NULL)
-       return 1;
-
     if (strcmp(item, "database.path") == 0) {
        printf ("%s\n", notmuch_config_get_database_path (config));
     } else if (strcmp(item, "user.name") == 0) {
@@ -756,25 +748,17 @@ notmuch_config_command_get (void *ctx, char *item)
        g_strfreev (value);
     }
 
-    notmuch_config_close (config);
-
     return 0;
 }
 
 static int
-notmuch_config_command_set (void *ctx, char *item, int argc, char *argv[])
+notmuch_config_command_set (notmuch_config_t *config, char *item, int argc, char *argv[])
 {
-    notmuch_config_t *config;
     char *group, *key;
-    int ret;
 
     if (_item_split (item, &group, &key))
        return 1;
 
-    config = notmuch_config_open (ctx, NULL, FALSE);
-    if (config == NULL)
-       return 1;
-
     /* With only the name of an item, we clear it from the
      * configuration file.
      *
@@ -795,23 +779,15 @@ notmuch_config_command_set (void *ctx, char *item, int argc, char *argv[])
        break;
     }
 
-    ret = notmuch_config_save (config);
-    notmuch_config_close (config);
-
-    return ret;
+    return notmuch_config_save (config);
 }
 
 static int
-notmuch_config_command_list (void *ctx)
+notmuch_config_command_list (notmuch_config_t *config)
 {
-    notmuch_config_t *config;
     char **groups;
     size_t g, groups_length;
 
-    config = notmuch_config_open (ctx, NULL, FALSE);
-    if (config == NULL)
-       return 1;
-
     groups = g_key_file_get_groups (config->key_file, &groups_length);
     if (groups == NULL)
        return 1;
@@ -841,42 +817,45 @@ notmuch_config_command_list (void *ctx)
 
     g_strfreev (groups);
 
-    notmuch_config_close (config);
-
     return 0;
 }
 
 int
-notmuch_config_command (void *ctx, int argc, char *argv[])
+notmuch_config_command (notmuch_config_t *config, int argc, char *argv[])
 {
+    int ret;
+
     argc--; argv++; /* skip subcommand argument */
 
     if (argc < 1) {
        fprintf (stderr, "Error: notmuch config requires at least one argument.\n");
-       return 1;
+       return EXIT_FAILURE;
     }
 
     if (strcmp (argv[0], "get") == 0) {
        if (argc != 2) {
            fprintf (stderr, "Error: notmuch config get requires exactly "
                     "one argument.\n");
-           return 1;
+           return EXIT_FAILURE;
        }
-       return notmuch_config_command_get (ctx, argv[1]);
+       ret = notmuch_config_command_get (config, argv[1]);
     } else if (strcmp (argv[0], "set") == 0) {
        if (argc < 2) {
            fprintf (stderr, "Error: notmuch config set requires at least "
                     "one argument.\n");
-           return 1;
+           return EXIT_FAILURE;
        }
-       return notmuch_config_command_set (ctx, argv[1], argc - 2, argv + 2);
+       ret = notmuch_config_command_set (config, argv[1], argc - 2, argv + 2);
     } else if (strcmp (argv[0], "list") == 0) {
-       return notmuch_config_command_list (ctx);
+       ret = notmuch_config_command_list (config);
+    } else {
+       fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
+                argv[0]);
+       return EXIT_FAILURE;
     }
 
-    fprintf (stderr, "Unrecognized argument for notmuch config: %s\n",
-            argv[0]);
-    return 1;
+    return ret ? EXIT_FAILURE : EXIT_SUCCESS;
+
 }
 
 notmuch_bool_t