1 // Copyright (C) 2011-2018 Joel Rosdahl
3 // This program is free software; you can redistribute it and/or modify it
4 // under the terms of the GNU General Public License as published by the Free
5 // Software Foundation; either version 3 of the License, or (at your option)
8 // This program is distributed in the hope that it will be useful, but WITHOUT
9 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 // You should have received a copy of the GNU General Public License along with
14 // this program; if not, write to the Free Software Foundation, Inc., 51
15 // Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 #include "confitems.h"
19 #include "envtoconfitems.h"
22 static const struct conf_item *
23 find_conf(const char *name)
25 return confitems_get(name, strlen(name));
28 static const struct env_to_conf_item *
29 find_env_to_conf(const char *name)
31 return envtoconfitems_get(name, strlen(name));
35 handle_conf_setting(struct conf *conf, const char *key, const char *value,
36 char **errmsg, bool from_env_variable, bool negate_boolean,
39 const struct conf_item *item = find_conf(key);
41 *errmsg = format("unknown configuration option \"%s\"", key);
45 if (from_env_variable && item->parser == confitem_parse_bool) {
46 // Special rule for boolean settings from the environment: "0", "false",
47 // "disable" and "no" (case insensitive) are invalid, and all other values
50 // Previously any value meant true, but this was surprising to users, who
51 // might do something like CCACHE_DISABLE=0 and expect ccache to be
53 if (str_eq(value, "0") || strcasecmp(value, "false") == 0
54 || strcasecmp(value, "disable") == 0 || strcasecmp(value, "no") == 0) {
55 fatal("invalid boolean environment variable value \"%s\"", value);
58 bool *boolvalue = (bool *)((char *)conf + item->offset);
59 *boolvalue = !negate_boolean;
63 if (!item->parser(value, (char *)conf + item->offset, errmsg)) {
66 if (item->verifier && !item->verifier((char *)conf + item->offset, errmsg)) {
71 conf->item_origins[item->number] = origin;
76 parse_line(const char *line, char **key, char **value, char **errmsg)
78 #define SKIP_WS(x) while (isspace(*x)) { ++x; }
85 if (*p == '\0' || *p == '#') {
89 while (isalpha(*q) || *q == '_') {
92 *key = x_strndup(p, q - p);
96 *errmsg = x_strdup("missing equal sign");
103 // Skip leading whitespace.
109 // Skip trailing whitespace.
110 while (isspace(q[-1])) {
113 *value = x_strndup(p, q - p);
120 // Create a conf struct with default values.
124 struct conf *conf = x_malloc(sizeof(*conf));
125 conf->base_dir = x_strdup("");
126 conf->cache_dir = format("%s/.ccache", get_home_directory());
127 conf->cache_dir_levels = 2;
128 conf->compiler = x_strdup("");
129 conf->compiler_check = x_strdup("mtime");
130 conf->compression = false;
131 conf->compression_level = 6;
132 conf->cpp_extension = x_strdup("");
134 conf->direct_mode = true;
135 conf->disable = false;
136 conf->extra_files_to_hash = x_strdup("");
137 conf->hard_link = false;
138 conf->hash_dir = true;
139 conf->ignore_headers_in_manifest = x_strdup("");
140 conf->keep_comments_cpp = false;
141 conf->limit_multiple = 0.8;
142 conf->log_file = x_strdup("");
144 conf->max_size = (uint64_t)5 * 1000 * 1000 * 1000;
145 conf->path = x_strdup("");
146 conf->pch_external_checksum = false;
147 conf->prefix_command = x_strdup("");
148 conf->prefix_command_cpp = x_strdup("");
149 conf->read_only = false;
150 conf->read_only_direct = false;
151 conf->recache = false;
152 conf->run_second_cpp = true;
153 conf->sloppiness = 0;
155 conf->temporary_dir = x_strdup("");
156 conf->umask = UINT_MAX; // Default: don't set umask.
158 conf->item_origins = x_malloc(confitems_count() * sizeof(char *));
159 for (size_t i = 0; i < confitems_count(); ++i) {
160 conf->item_origins[i] = "default";
166 conf_free(struct conf *conf)
171 free(conf->base_dir);
172 free(conf->cache_dir);
173 free(conf->compiler);
174 free(conf->compiler_check);
175 free(conf->cpp_extension);
176 free(conf->extra_files_to_hash);
177 free(conf->ignore_headers_in_manifest);
178 free(conf->log_file);
180 free(conf->prefix_command);
181 free(conf->prefix_command_cpp);
182 free(conf->temporary_dir);
183 free((void *)conf->item_origins); // Workaround for MSVC warning
187 // Note: The path pointer is stored in conf, so path must outlive conf.
189 // On failure, if an I/O error occured errno is set approriately, otherwise
190 // errno is set to zero indicating that config itself was invalid.
192 conf_read(struct conf *conf, const char *path, char **errmsg)
197 FILE *f = fopen(path, "r");
199 *errmsg = format("%s: %s", path, strerror(errno));
203 unsigned line_number = 0;
206 while (fgets(buf, sizeof(buf), f)) {
212 bool ok = parse_line(buf, &key, &value, &errmsg2);
213 if (ok && key) { // key == NULL if comment or blank line.
214 ok = handle_conf_setting(conf, key, value, &errmsg2, false, false, path);
219 *errmsg = format("%s:%u: %s", path, line_number, errmsg2);
227 *errmsg = x_strdup(strerror(errno));
237 conf_update_from_environment(struct conf *conf, char **errmsg)
239 for (char **p = environ; *p; ++p) {
240 if (!str_startswith(*p, "CCACHE_")) {
243 char *q = strchr(*p, '=');
250 if (str_startswith(*p + 7, "NO")) {
257 char *key = x_strndup(*p + key_start, q - *p - key_start);
259 ++q; // Now points to the value.
261 const struct env_to_conf_item *env_to_conf_item = find_env_to_conf(key);
262 if (!env_to_conf_item) {
268 bool ok = handle_conf_setting(
269 conf, env_to_conf_item->conf_name, q, &errmsg2, true, negate,
272 *errmsg = format("%s: %s", key, errmsg2);
285 conf_set_value_in_file(const char *path, const char *key, const char *value,
288 const struct conf_item *item = find_conf(key);
290 *errmsg = format("unknown configuration option \"%s\"", key);
294 FILE *infile = fopen(path, "r");
296 *errmsg = format("%s: %s", path, strerror(errno));
300 char *outpath = format("%s.tmp", path);
301 FILE *outfile = create_tmp_file(&outpath, "w");
303 *errmsg = format("%s: %s", outpath, strerror(errno));
311 while (fgets(buf, sizeof(buf), infile)) {
315 bool ok = parse_line(buf, &key2, &value2, &errmsg2);
316 if (ok && key2 && str_eq(key2, key)) {
318 fprintf(outfile, "%s = %s\n", key, value);
327 fprintf(outfile, "%s = %s\n", key, value);
332 if (x_rename(outpath, path) != 0) {
333 *errmsg = format("rename %s to %s: %s", outpath, path, strerror(errno));
342 conf_print_value(struct conf *conf, const char *key,
343 FILE *file, char **errmsg)
345 const struct conf_item *item = find_conf(key);
347 *errmsg = format("unknown configuration option \"%s\"", key);
350 void *value = (char *)conf + item->offset;
351 char *str = item->formatter(value);
352 fprintf(file, "%s\n", str);
358 print_item(struct conf *conf, const char *key,
359 void (*printer)(const char *descr, const char *origin,
363 const struct conf_item *item = find_conf(key);
367 void *value = (char *)conf + item->offset;
368 char *str = item->formatter(value);
369 char *buf = x_strdup("");
370 reformat(&buf, "%s = %s", key, str);
371 printer(buf, conf->item_origins[item->number], context);
378 conf_print_items(struct conf *conf,
379 void (*printer)(const char *descr, const char *origin,
384 ok &= print_item(conf, "base_dir", printer, context);
385 ok &= print_item(conf, "cache_dir", printer, context);
386 ok &= print_item(conf, "cache_dir_levels", printer, context);
387 ok &= print_item(conf, "compiler", printer, context);
388 ok &= print_item(conf, "compiler_check", printer, context);
389 ok &= print_item(conf, "compression", printer, context);
390 ok &= print_item(conf, "compression_level", printer, context);
391 ok &= print_item(conf, "cpp_extension", printer, context);
392 ok &= print_item(conf, "debug", printer, context);
393 ok &= print_item(conf, "direct_mode", printer, context);
394 ok &= print_item(conf, "disable", printer, context);
395 ok &= print_item(conf, "extra_files_to_hash", printer, context);
396 ok &= print_item(conf, "hard_link", printer, context);
397 ok &= print_item(conf, "hash_dir", printer, context);
398 ok &= print_item(conf, "ignore_headers_in_manifest", printer, context);
399 ok &= print_item(conf, "keep_comments_cpp", printer, context);
400 ok &= print_item(conf, "limit_multiple", printer, context);
401 ok &= print_item(conf, "log_file", printer, context);
402 ok &= print_item(conf, "max_files", printer, context);
403 ok &= print_item(conf, "max_size", printer, context);
404 ok &= print_item(conf, "path", printer, context);
405 ok &= print_item(conf, "pch_external_checksum", printer, context);
406 ok &= print_item(conf, "prefix_command", printer, context);
407 ok &= print_item(conf, "prefix_command_cpp", printer, context);
408 ok &= print_item(conf, "read_only", printer, context);
409 ok &= print_item(conf, "read_only_direct", printer, context);
410 ok &= print_item(conf, "recache", printer, context);
411 ok &= print_item(conf, "run_second_cpp", printer, context);
412 ok &= print_item(conf, "sloppiness", printer, context);
413 ok &= print_item(conf, "stats", printer, context);
414 ok &= print_item(conf, "temporary_dir", printer, context);
415 ok &= print_item(conf, "umask", printer, context);
416 ok &= print_item(conf, "unify", printer, context);