Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * builtin-config.c
0004  *
0005  * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com>
0006  *
0007  */
0008 #include "builtin.h"
0009 
0010 #include "util/cache.h"
0011 #include <subcmd/parse-options.h>
0012 #include "util/debug.h"
0013 #include "util/config.h"
0014 #include <linux/string.h>
0015 #include <stdio.h>
0016 #include <stdlib.h>
0017 
0018 static bool use_system_config, use_user_config;
0019 
0020 static const char * const config_usage[] = {
0021     "perf config [<file-option>] [options] [section.name[=value] ...]",
0022     NULL
0023 };
0024 
0025 enum actions {
0026     ACTION_LIST = 1
0027 } actions;
0028 
0029 static struct option config_options[] = {
0030     OPT_SET_UINT('l', "list", &actions,
0031              "show current config variables", ACTION_LIST),
0032     OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"),
0033     OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"),
0034     OPT_END()
0035 };
0036 
0037 static int set_config(struct perf_config_set *set, const char *file_name)
0038 {
0039     struct perf_config_section *section = NULL;
0040     struct perf_config_item *item = NULL;
0041     const char *first_line = "# this file is auto-generated.";
0042     FILE *fp;
0043 
0044     if (set == NULL)
0045         return -1;
0046 
0047     fp = fopen(file_name, "w");
0048     if (!fp)
0049         return -1;
0050 
0051     fprintf(fp, "%s\n", first_line);
0052 
0053     /* overwrite configvariables */
0054     perf_config_items__for_each_entry(&set->sections, section) {
0055         if (!use_system_config && section->from_system_config)
0056             continue;
0057         fprintf(fp, "[%s]\n", section->name);
0058 
0059         perf_config_items__for_each_entry(&section->items, item) {
0060             if (!use_system_config && item->from_system_config)
0061                 continue;
0062             if (item->value)
0063                 fprintf(fp, "\t%s = %s\n",
0064                     item->name, item->value);
0065         }
0066     }
0067     fclose(fp);
0068 
0069     return 0;
0070 }
0071 
0072 static int show_spec_config(struct perf_config_set *set, const char *var)
0073 {
0074     struct perf_config_section *section;
0075     struct perf_config_item *item;
0076 
0077     if (set == NULL)
0078         return -1;
0079 
0080     perf_config_items__for_each_entry(&set->sections, section) {
0081         if (!strstarts(var, section->name))
0082             continue;
0083 
0084         perf_config_items__for_each_entry(&section->items, item) {
0085             const char *name = var + strlen(section->name) + 1;
0086 
0087             if (strcmp(name, item->name) == 0) {
0088                 char *value = item->value;
0089 
0090                 if (value) {
0091                     printf("%s=%s\n", var, value);
0092                     return 0;
0093                 }
0094             }
0095 
0096         }
0097     }
0098 
0099     return 0;
0100 }
0101 
0102 static int show_config(struct perf_config_set *set)
0103 {
0104     struct perf_config_section *section;
0105     struct perf_config_item *item;
0106 
0107     if (set == NULL)
0108         return -1;
0109 
0110     perf_config_set__for_each_entry(set, section, item) {
0111         char *value = item->value;
0112 
0113         if (value)
0114             printf("%s.%s=%s\n", section->name,
0115                    item->name, value);
0116     }
0117 
0118     return 0;
0119 }
0120 
0121 static int parse_config_arg(char *arg, char **var, char **value)
0122 {
0123     const char *last_dot = strchr(arg, '.');
0124 
0125     /*
0126      * Since "var" actually contains the section name and the real
0127      * config variable name separated by a dot, we have to know where the dot is.
0128      */
0129     if (last_dot == NULL || last_dot == arg) {
0130         pr_err("The config variable does not contain a section name: %s\n", arg);
0131         return -1;
0132     }
0133     if (!last_dot[1]) {
0134         pr_err("The config variable does not contain a variable name: %s\n", arg);
0135         return -1;
0136     }
0137 
0138     *value = strchr(arg, '=');
0139     if (*value == NULL)
0140         *var = arg;
0141     else if (!strcmp(*value, "=")) {
0142         pr_err("The config variable does not contain a value: %s\n", arg);
0143         return -1;
0144     } else {
0145         *value = *value + 1; /* excluding a first character '=' */
0146         *var = strsep(&arg, "=");
0147         if (*var[0] == '\0') {
0148             pr_err("invalid config variable: %s\n", arg);
0149             return -1;
0150         }
0151     }
0152 
0153     return 0;
0154 }
0155 
0156 int cmd_config(int argc, const char **argv)
0157 {
0158     int i, ret = -1;
0159     struct perf_config_set *set;
0160     char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
0161     const char *config_filename;
0162     bool changed = false;
0163 
0164     argc = parse_options(argc, argv, config_options, config_usage,
0165                  PARSE_OPT_STOP_AT_NON_OPTION);
0166 
0167     if (use_system_config && use_user_config) {
0168         pr_err("Error: only one config file at a time\n");
0169         parse_options_usage(config_usage, config_options, "user", 0);
0170         parse_options_usage(NULL, config_options, "system", 0);
0171         return -1;
0172     }
0173 
0174     if (use_system_config)
0175         config_exclusive_filename = perf_etc_perfconfig();
0176     else if (use_user_config)
0177         config_exclusive_filename = user_config;
0178 
0179     if (!config_exclusive_filename)
0180         config_filename = user_config;
0181     else
0182         config_filename = config_exclusive_filename;
0183 
0184     /*
0185      * At only 'config' sub-command, individually use the config set
0186      * because of reinitializing with options config file location.
0187      */
0188     set = perf_config_set__new();
0189     if (!set)
0190         goto out_err;
0191 
0192     switch (actions) {
0193     case ACTION_LIST:
0194         if (argc) {
0195             pr_err("Error: takes no arguments\n");
0196             parse_options_usage(config_usage, config_options, "l", 1);
0197         } else {
0198 do_action_list:
0199             if (show_config(set) < 0) {
0200                 pr_err("Nothing configured, "
0201                        "please check your %s \n", config_filename);
0202                 goto out_err;
0203             }
0204         }
0205         break;
0206     default:
0207         if (!argc)
0208             goto do_action_list;
0209 
0210         for (i = 0; argv[i]; i++) {
0211             char *var, *value;
0212             char *arg = strdup(argv[i]);
0213 
0214             if (!arg) {
0215                 pr_err("%s: strdup failed\n", __func__);
0216                 goto out_err;
0217             }
0218 
0219             if (parse_config_arg(arg, &var, &value) < 0) {
0220                 free(arg);
0221                 goto out_err;
0222             }
0223 
0224             if (value == NULL) {
0225                 if (show_spec_config(set, var) < 0) {
0226                     pr_err("%s is not configured: %s\n",
0227                            var, config_filename);
0228                     free(arg);
0229                     goto out_err;
0230                 }
0231             } else {
0232                 if (perf_config_set__collect(set, config_filename,
0233                                  var, value) < 0) {
0234                     pr_err("Failed to add '%s=%s'\n",
0235                            var, value);
0236                     free(arg);
0237                     goto out_err;
0238                 }
0239                 changed = true;
0240             }
0241             free(arg);
0242         }
0243 
0244         if (!changed)
0245             break;
0246 
0247         if (set_config(set, config_filename) < 0) {
0248             pr_err("Failed to set the configs on %s\n",
0249                    config_filename);
0250             goto out_err;
0251         }
0252     }
0253 
0254     ret = 0;
0255 out_err:
0256     perf_config_set__delete(set);
0257     return ret;
0258 }