⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 config.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * config.c :  reading configuration information * * ==================================================================== * Copyright (c) 2000-2004 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#define APR_WANT_STRFUNC#define APR_WANT_MEMFUNC#include <apr_want.h>#include <apr_general.h>#include <apr_lib.h>#include "svn_error.h"#include "svn_pools.h"#include "config_impl.h"#include "svn_private_config.h"/* Section table entries. */typedef struct cfg_section_t cfg_section_t;struct cfg_section_t{  /* The section name. */  const char *name;  /* The section name, converted into a hash key. */  const char *hash_key;  /* Table of cfg_option_t's. */  apr_hash_t *options;};/* Option table entries. */typedef struct cfg_option_t cfg_option_t;struct cfg_option_t{  /* The option name. */  const char *name;  /* The option name, converted into a hash key. */  const char *hash_key;  /* The unexpanded option value. */  const char *value;  /* The expanded option value. */  const char *x_value;  /* Expansion flag. If this is TRUE, this value has already been expanded.     In this case, if x_value is NULL, no expansions were necessary,     and value should be used directly. */  svn_boolean_t expanded;};svn_error_t *svn_config_read(svn_config_t **cfgp, const char *file,                svn_boolean_t must_exist, apr_pool_t *pool){  svn_config_t *cfg = apr_palloc(pool, sizeof(*cfg));  svn_error_t *err;  cfg->sections = apr_hash_make(pool);  cfg->pool = pool;  cfg->x_pool = svn_pool_create(pool);  cfg->x_values = FALSE;  cfg->tmp_key = svn_stringbuf_create("", pool);  cfg->tmp_value = svn_stringbuf_create("", pool);  /* Yes, this is platform-specific code in Subversion, but there's no     practical way to migrate it into APR, as it's simultaneously     Subversion-specific and Windows-specific.  Even if we eventually     want to have APR offer a generic config-reading interface, it     makes sense to test it here first and migrate it later. */#ifdef WIN32  if (0 == strncmp(file, SVN_REGISTRY_PREFIX, SVN_REGISTRY_PREFIX_LEN))    err = svn_config__parse_registry(cfg, file + SVN_REGISTRY_PREFIX_LEN,                                     must_exist, pool);  else#endif /* WIN32 */    err = svn_config__parse_file(cfg, file, must_exist, pool);  if (err != SVN_NO_ERROR)    return err;  else    *cfgp = cfg;  return SVN_NO_ERROR;}/* Read various configuration sources into *CFGP, in this order, with * later reads overriding the results of earlier ones: * *    1. SYS_REGISTRY_PATH   (only on Win32, but ignored if NULL) * *    2. SYS_FILE_PATH       (everywhere, but ignored if NULL) * *    3. USR_REGISTRY_PATH   (only on Win32, but ignored if NULL) * *    4. USR_FILE_PATH       (everywhere, but ignored if NULL) * * Allocate *CFGP in POOL.  Even if no configurations are read, * allocate an empty *CFGP. */static svn_error_t *read_all(svn_config_t **cfgp,         const char *sys_registry_path,         const char *usr_registry_path,         const char *sys_file_path,         const char *usr_file_path,         apr_pool_t *pool){  svn_boolean_t red_config = FALSE;  /* "red" is the past tense of "read" */  /*** Read system-wide configurations first... ***/#ifdef WIN32  if (sys_registry_path)    {      SVN_ERR(svn_config_read(cfgp, sys_registry_path, FALSE, pool));      red_config = TRUE;    }#endif /* WIN32 */  if (sys_file_path)    {      if (red_config)        SVN_ERR(svn_config_merge(*cfgp, sys_file_path, FALSE));      else        {          SVN_ERR(svn_config_read(cfgp, sys_file_path, FALSE, pool));          red_config = TRUE;        }    }  /*** ...followed by per-user configurations. ***/#ifdef WIN32  if (usr_registry_path)    {      if (red_config)        SVN_ERR(svn_config_merge(*cfgp, usr_registry_path, FALSE));      else        {          SVN_ERR(svn_config_read(cfgp, usr_registry_path, FALSE, pool));          red_config = TRUE;        }    }#endif /* WIN32 */  if (usr_file_path)    {      if (red_config)        SVN_ERR(svn_config_merge(*cfgp, usr_file_path, FALSE));      else        {          SVN_ERR(svn_config_read(cfgp, usr_file_path, FALSE, pool));          red_config = TRUE;        }    }  if (! red_config)    *cfgp = NULL;  return SVN_NO_ERROR;}static svn_error_t *get_category_config(svn_config_t **cfg,                    const char *config_dir,                    const char *category,                    apr_pool_t *pool){  const char *usr_reg_path = NULL, *sys_reg_path = NULL;  const char *usr_cfg_path, *sys_cfg_path;    *cfg = NULL;  if (! config_dir)    {#ifdef WIN32      sys_reg_path = apr_pstrcat(pool, SVN_REGISTRY_SYS_CONFIG_PATH,                                 category, NULL);      usr_reg_path = apr_pstrcat(pool, SVN_REGISTRY_USR_CONFIG_PATH,                                 category, NULL);#endif /* WIN32 */      SVN_ERR(svn_config__sys_config_path(&sys_cfg_path, category, pool));    }  else    sys_cfg_path = NULL;  SVN_ERR(svn_config__user_config_path(config_dir, &usr_cfg_path, category,                                       pool));  SVN_ERR(read_all(cfg,                   sys_reg_path, usr_reg_path,                   sys_cfg_path, usr_cfg_path,                   pool));  return SVN_NO_ERROR;}svn_error_t *svn_config_get_config(apr_hash_t **cfg_hash,                      const char *config_dir,                      apr_pool_t *pool){  svn_config_t *cfg;  *cfg_hash = apr_hash_make(pool);  #define CATLEN (sizeof(SVN_CONFIG_CATEGORY_SERVERS) - 1)  SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_SERVERS,                              pool));  if (cfg)    apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_SERVERS, CATLEN, cfg);#undef CATLEN#define CATLEN (sizeof(SVN_CONFIG_CATEGORY_CONFIG) - 1)  SVN_ERR(get_category_config(&cfg, config_dir, SVN_CONFIG_CATEGORY_CONFIG,                              pool));  if (cfg)    apr_hash_set(*cfg_hash, SVN_CONFIG_CATEGORY_CONFIG, CATLEN, cfg);#undef CATLEN  return SVN_NO_ERROR;}/* Iterate through CFG, passing BATON to CALLBACK for every (SECTION, OPTION)   pair.  Stop if CALLBACK returns TRUE.  Allocate from POOL. */static voidfor_each_option(svn_config_t *cfg, void *baton, apr_pool_t *pool,                svn_boolean_t callback(void *same_baton,                                       cfg_section_t *section,                                       cfg_option_t *option)){  apr_hash_index_t *sec_ndx;  for (sec_ndx = apr_hash_first(pool, cfg->sections);       sec_ndx != NULL;       sec_ndx = apr_hash_next(sec_ndx))    {      void *sec_ptr;      cfg_section_t *sec;      apr_hash_index_t *opt_ndx;      apr_hash_this(sec_ndx, NULL, NULL, &sec_ptr);      sec = sec_ptr;      for (opt_ndx = apr_hash_first(pool, sec->options);           opt_ndx != NULL;           opt_ndx = apr_hash_next(opt_ndx))        {          void *opt_ptr;          cfg_option_t *opt;          apr_hash_this(opt_ndx, NULL, NULL, &opt_ptr);          opt = opt_ptr;          if (callback(baton, sec, opt))            return;        }    }}static svn_boolean_tmerge_callback(void *baton, cfg_section_t *section, cfg_option_t *option){  svn_config_set(baton, section->name, option->name, option->value);  return FALSE;}svn_error_t *svn_config_merge(svn_config_t *cfg, const char *file,                 svn_boolean_t must_exist){  /* The original config hash shouldn't change if there's an error     while reading the confguration, so read into a temporary table.     ### We could use a tmp subpool for this, since merge_cfg is going     to be tossed afterwards.  Premature optimization, though? */  svn_config_t *merge_cfg;  SVN_ERR(svn_config_read(&merge_cfg, file, must_exist, cfg->pool));  /* Now copy the new options into the original table. */  for_each_option(merge_cfg, cfg, merge_cfg->pool, merge_callback);  return SVN_NO_ERROR;}/* Remove variable expansions from CFG.  Walk through the options tree,   killing all expanded values, then clear the expanded value pool. */static svn_boolean_trmex_callback(void *baton, cfg_section_t *section, cfg_option_t *option){  /* Only clear the `expanded' flag if the value actually contains     variable expansions. */  if (option->expanded && option->x_value != NULL)    {      option->x_value = NULL;      option->expanded = FALSE;    }  return FALSE;}static voidremove_expansions(svn_config_t *cfg){  if (!cfg->x_values)    return;  for_each_option(cfg, NULL, cfg->x_pool, rmex_callback);  apr_pool_clear(cfg->x_pool);  cfg->x_values = FALSE;}/* Canonicalize a string for hashing.  Modifies KEY in place. */static APR_INLINE char *make_hash_key(char *key){  register char *p;  for (p = key; *p != 0; ++p)    *p = apr_tolower(*p);  return key;}/* Return a pointer to an option in CFG, or NULL if it doesn't exist.   if SECTIONP is non-null, return a pointer to the option's section.   OPTION may be NULL. */static cfg_option_t *find_option(svn_config_t *cfg, const char *section, const char *option,            cfg_section_t **sectionp){  void *sec_ptr;  /* Canonicalize the hash key */  svn_stringbuf_set(cfg->tmp_key, section);  make_hash_key(cfg->tmp_key->data);  sec_ptr = apr_hash_get(cfg->sections, cfg->tmp_key->data,                         cfg->tmp_key->len);  if (sectionp != NULL)    *sectionp = sec_ptr;  if (sec_ptr != NULL && option != NULL)    {      cfg_section_t *sec = sec_ptr;      cfg_option_t *opt;      /* Canonicalize the option key */      svn_stringbuf_set(cfg->tmp_key, option);      make_hash_key(cfg->tmp_key->data);      opt = apr_hash_get(sec->options, cfg->tmp_key->data,                         cfg->tmp_key->len);      /* NOTE: ConfigParser's sections are case sensitive. */      if (opt == NULL          && apr_strnatcasecmp(section, SVN_CONFIG__DEFAULT_SECTION) != 0)        /* Options which aren't found in the requested section are           also sought after in the default section. */        opt = find_option(cfg, SVN_CONFIG__DEFAULT_SECTION, option, &sec);      return opt;    }  return NULL;}/* Has a bi-directional dependency with make_string_from_option(). */static voidexpand_option_value(svn_config_t *cfg, cfg_section_t *section,                    const char *opt_value, const char **opt_x_valuep,                    apr_pool_t *x_pool);/* Set *VALUEP according to the OPT's value.  A value for X_POOL must   only ever be passed into this function by expand_option_value(). */static voidmake_string_from_option(const char **valuep, svn_config_t *cfg,                        cfg_section_t *section, cfg_option_t *opt,                        apr_pool_t* x_pool){  /* Expand the option value if necessary. */  if (!opt->expanded)    {      apr_pool_t *tmp_pool = (x_pool ? x_pool : svn_pool_create(cfg->x_pool));      expand_option_value(cfg, section, opt->value, &opt->x_value, tmp_pool);      opt->expanded = TRUE;      if (!x_pool)        {          /* Grab the fully expanded value from tmp_pool before its             disappearing act. */          if (opt->x_value)            opt->x_value = apr_pstrmemdup(cfg->x_pool, opt->x_value,                                          strlen(opt->x_value));          svn_pool_destroy(tmp_pool);        }    }  if (opt->x_value)    *valuep = opt->x_value;  else    *valuep = opt->value;}/* Start of variable-replacement placeholder */#define FMT_START     "%("#define FMT_START_LEN (sizeof(FMT_START) - 1)/* End of variable-replacement placeholder */#define FMT_END       ")s"#define FMT_END_LEN   (sizeof(FMT_END) - 1)/* Expand OPT_VALUE (which may be NULL) in SECTION into *OPT_X_VALUEP.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -