Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/perf/builtin-config.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* builtin-config.c
4
*
5
* Copyright (C) 2015, Taeung Song <[email protected]>
6
*
7
*/
8
#include "builtin.h"
9
10
#include "util/cache.h"
11
#include <subcmd/parse-options.h>
12
#include "util/debug.h"
13
#include "util/config.h"
14
#include <linux/string.h>
15
#include <limits.h>
16
#include <stdio.h>
17
#include <stdlib.h>
18
19
static bool use_system_config, use_user_config;
20
21
static const char * const config_usage[] = {
22
"perf config [<file-option>] [options] [section.name[=value] ...]",
23
NULL
24
};
25
26
enum actions {
27
ACTION_LIST = 1
28
} actions;
29
30
static struct option config_options[] = {
31
OPT_SET_UINT('l', "list", &actions,
32
"show current config variables", ACTION_LIST),
33
OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
34
OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
35
OPT_END()
36
};
37
38
static int set_config(struct perf_config_set *set, const char *file_name)
39
{
40
struct perf_config_section *section = NULL;
41
struct perf_config_item *item = NULL;
42
const char *first_line = "# this file is auto-generated.";
43
FILE *fp;
44
45
if (set == NULL)
46
return -1;
47
48
fp = fopen(file_name, "w");
49
if (!fp)
50
return -1;
51
52
fprintf(fp, "%s\n", first_line);
53
54
/* overwrite configvariables */
55
perf_config_items__for_each_entry(&set->sections, section) {
56
if (!use_system_config && section->from_system_config)
57
continue;
58
fprintf(fp, "[%s]\n", section->name);
59
60
perf_config_items__for_each_entry(&section->items, item) {
61
if (!use_system_config && item->from_system_config)
62
continue;
63
if (item->value)
64
fprintf(fp, "\t%s = %s\n",
65
item->name, item->value);
66
}
67
}
68
fclose(fp);
69
70
return 0;
71
}
72
73
static int show_spec_config(struct perf_config_set *set, const char *var)
74
{
75
struct perf_config_section *section;
76
struct perf_config_item *item;
77
78
if (set == NULL)
79
return -1;
80
81
perf_config_items__for_each_entry(&set->sections, section) {
82
if (!strstarts(var, section->name))
83
continue;
84
85
perf_config_items__for_each_entry(&section->items, item) {
86
const char *name = var + strlen(section->name) + 1;
87
88
if (strcmp(name, item->name) == 0) {
89
char *value = item->value;
90
91
if (value) {
92
printf("%s=%s\n", var, value);
93
return 0;
94
}
95
}
96
97
}
98
}
99
100
return 0;
101
}
102
103
static int show_config(struct perf_config_set *set)
104
{
105
struct perf_config_section *section;
106
struct perf_config_item *item;
107
108
if (set == NULL)
109
return -1;
110
111
perf_config_set__for_each_entry(set, section, item) {
112
char *value = item->value;
113
114
if (value)
115
printf("%s.%s=%s\n", section->name,
116
item->name, value);
117
}
118
119
return 0;
120
}
121
122
static int parse_config_arg(char *arg, char **var, char **value)
123
{
124
const char *last_dot = strchr(arg, '.');
125
126
/*
127
* Since "var" actually contains the section name and the real
128
* config variable name separated by a dot, we have to know where the dot is.
129
*/
130
if (last_dot == NULL || last_dot == arg) {
131
pr_err("The config variable does not contain a section name: %s\n", arg);
132
return -1;
133
}
134
if (!last_dot[1]) {
135
pr_err("The config variable does not contain a variable name: %s\n", arg);
136
return -1;
137
}
138
139
*value = strchr(arg, '=');
140
if (*value == NULL)
141
*var = arg;
142
else if (!strcmp(*value, "=")) {
143
pr_err("The config variable does not contain a value: %s\n", arg);
144
return -1;
145
} else {
146
*value = *value + 1; /* excluding a first character '=' */
147
*var = strsep(&arg, "=");
148
if (*var[0] == '\0') {
149
pr_err("invalid config variable: %s\n", arg);
150
return -1;
151
}
152
}
153
154
return 0;
155
}
156
157
int perf_config__set_variable(const char *var, const char *value)
158
{
159
char path[PATH_MAX];
160
char *user_config = mkpath(path, sizeof(path), "%s/.perfconfig", getenv("HOME"));
161
const char *config_filename;
162
struct perf_config_set *set;
163
int ret = -1;
164
165
if (use_system_config)
166
config_exclusive_filename = perf_etc_perfconfig();
167
else if (use_user_config)
168
config_exclusive_filename = user_config;
169
170
if (!config_exclusive_filename)
171
config_filename = user_config;
172
else
173
config_filename = config_exclusive_filename;
174
175
set = perf_config_set__new();
176
if (!set)
177
goto out_err;
178
179
if (perf_config_set__collect(set, config_filename, var, value) < 0) {
180
pr_err("Failed to add '%s=%s'\n", var, value);
181
goto out_err;
182
}
183
184
if (set_config(set, config_filename) < 0) {
185
pr_err("Failed to set the configs on %s\n", config_filename);
186
goto out_err;
187
}
188
189
ret = 0;
190
out_err:
191
perf_config_set__delete(set);
192
return ret;
193
}
194
195
int cmd_config(int argc, const char **argv)
196
{
197
int i, ret = -1;
198
struct perf_config_set *set;
199
char path[PATH_MAX];
200
char *user_config = mkpath(path, sizeof(path), "%s/.perfconfig", getenv("HOME"));
201
const char *config_filename;
202
bool changed = false;
203
204
argc = parse_options(argc, argv, config_options, config_usage,
205
PARSE_OPT_STOP_AT_NON_OPTION);
206
207
if (use_system_config && use_user_config) {
208
pr_err("Error: only one config file at a time\n");
209
parse_options_usage(config_usage, config_options, "user", 0);
210
parse_options_usage(NULL, config_options, "system", 0);
211
return -1;
212
}
213
214
if (use_system_config)
215
config_exclusive_filename = perf_etc_perfconfig();
216
else if (use_user_config)
217
config_exclusive_filename = user_config;
218
219
if (!config_exclusive_filename)
220
config_filename = user_config;
221
else
222
config_filename = config_exclusive_filename;
223
224
/*
225
* At only 'config' sub-command, individually use the config set
226
* because of reinitializing with options config file location.
227
*/
228
set = perf_config_set__new();
229
if (!set)
230
goto out_err;
231
232
switch (actions) {
233
case ACTION_LIST:
234
if (argc) {
235
pr_err("Error: takes no arguments\n");
236
parse_options_usage(config_usage, config_options, "l", 1);
237
} else {
238
do_action_list:
239
if (show_config(set) < 0) {
240
pr_err("Nothing configured, "
241
"please check your %s \n", config_filename);
242
goto out_err;
243
}
244
}
245
break;
246
default:
247
if (!argc)
248
goto do_action_list;
249
250
for (i = 0; argv[i]; i++) {
251
char *var, *value;
252
char *arg = strdup(argv[i]);
253
254
if (!arg) {
255
pr_err("%s: strdup failed\n", __func__);
256
goto out_err;
257
}
258
259
if (parse_config_arg(arg, &var, &value) < 0) {
260
free(arg);
261
goto out_err;
262
}
263
264
if (value == NULL) {
265
if (show_spec_config(set, var) < 0) {
266
pr_err("%s is not configured: %s\n",
267
var, config_filename);
268
free(arg);
269
goto out_err;
270
}
271
} else {
272
if (perf_config_set__collect(set, config_filename,
273
var, value) < 0) {
274
pr_err("Failed to add '%s=%s'\n",
275
var, value);
276
free(arg);
277
goto out_err;
278
}
279
changed = true;
280
}
281
free(arg);
282
}
283
284
if (!changed)
285
break;
286
287
if (set_config(set, config_filename) < 0) {
288
pr_err("Failed to set the configs on %s\n",
289
config_filename);
290
goto out_err;
291
}
292
}
293
294
ret = 0;
295
out_err:
296
perf_config_set__delete(set);
297
return ret;
298
}
299
300