]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
config: Implement conf_set_value_in_file()
authorJoel Rosdahl <joel@rosdahl.net>
Tue, 19 Jul 2011 10:44:20 +0000 (12:44 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Wed, 20 Jul 2011 21:31:38 +0000 (23:31 +0200)
conf.c
conf.h
test/test_conf.c

diff --git a/conf.c b/conf.c
index cd0b7c52c409eb263779147a9e1ed53966b041ad..383b1a8038c7fbe96826e29c436b752f1a10348f 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -550,3 +550,55 @@ conf_update_from_environment(struct conf *conf, char **errmsg)
 
        return true;
 }
+
+bool
+conf_set_value_in_file(const char *path, const char *key, const char *value,
+                       char **errmsg)
+{
+       FILE *infile, *outfile;
+       char *outpath;
+       char buf[10000];
+       bool found;
+
+       infile = fopen(path, "r");
+       if (!infile) {
+               *errmsg = format("%s: %s", path, strerror(errno));
+               return false;
+       }
+
+       outpath = format("%s.tmp.%s", path, tmp_string());
+       outfile = fopen(outpath, "w");
+       if (!outfile) {
+               *errmsg = format("%s: %s", outpath, strerror(errno));
+               free(outpath);
+               fclose(infile);
+               return false;
+       }
+
+       found = false;
+       while (fgets(buf, sizeof(buf), infile)) {
+               char *errmsg2, *key2, *value2;
+               bool ok;
+               ok = parse_line(buf, &key2, &value2, &errmsg2);
+               if (ok && key2 && str_eq(key2, key)) {
+                       found = true;
+                       fprintf(outfile, "%s = %s\n", key, value);
+               } else {
+                       fputs(buf, outfile);
+               }
+       }
+
+       if (!found) {
+               fprintf(outfile, "%s = %s\n", key, value);
+       }
+
+       fclose(infile);
+       fclose(outfile);
+       if (x_rename(outpath, path) != 0) {
+               *errmsg = format("rename %s to %s: %s", outpath, path, strerror(errno));
+               return false;
+       }
+       free(outpath);
+
+       return true;
+}
diff --git a/conf.h b/conf.h
index 0890b42bdded032dbdeb9a4243d26998c2c39f54..257faa966f7503708642ec90d735e022c724b56f 100644 (file)
--- a/conf.h
+++ b/conf.h
@@ -36,5 +36,7 @@ struct conf *conf_create(void);
 void conf_free(struct conf *conf);
 bool conf_read(struct conf *conf, const char *path, char **errmsg);
 bool conf_update_from_environment(struct conf *conf, char **errmsg);
+bool conf_set_value_in_file(const char *path, const char *key,
+                            const char *value, char **errmsg);
 
 #endif
index 5485848317c111f9a049a75f69c39a4f83dadeaa..4b6c09f8741f1ed125e4c7fb9ec98dbfb294e3cf 100644 (file)
@@ -302,4 +302,28 @@ TEST(conf_update_from_environment)
        conf_free(conf);
 }
 
+TEST(conf_set_new_value)
+{
+       char *errmsg;
+       char *data;
+
+       create_file("ccache.conf", "flavour = vanilla\n");
+       CHECK(conf_set_value_in_file("ccache.conf", "topping", "chocolate", &errmsg));
+       data = read_text_file("ccache.conf", 0);
+       CHECK(data);
+       CHECK_STR_EQ_FREE2("flavour = vanilla\ntopping = chocolate\n", data);
+}
+
+TEST(conf_set_existing_value)
+{
+       char *errmsg;
+       char *data;
+
+       create_file("ccache.conf", "flavour = chocolate\ntopping = chocolate\n");
+       CHECK(conf_set_value_in_file("ccache.conf", "flavour", "vanilla", &errmsg));
+       data = read_text_file("ccache.conf", 0);
+       CHECK(data);
+       CHECK_STR_EQ_FREE2("flavour = vanilla\ntopping = chocolate\n", data);
+}
+
 TEST_SUITE_END