I would appreciate a review of this. I'll do the commit.
Regards,
Blair
[[[
Add the ability to specificy a global svnserve configuration file
which will cause svnserve to ignore any per-repository configuration
files. This is enabled with the --config-file command line option.
* subversion/svnserve/server.h
(serve_params_t):
Add new fields:
cfg - A svn_config_t holding a svnserve config file.
pwdb - A svn_config_t holding a svnserve password file.
authzdb - A svn_authz_t holding a svnserve authorization file.
(load_configs):
New function to load the configuration files.
* subversion/svnserve/serve.c
(find_repos):
Move the code that loads the configuration, password and
authorization files from here...
(load_configs):
... into this new function.
(serve):
Instead of setting the server_baton_t's cfg, pwdb, authzdb fields
to NULL, get their initial values from the passed in
serve_params_t.
* subversion/svnserve/main.c:
(SVNSERVE_OPT_CONFIG_FILE):
New constant for the getopt parsing.
(svnserve__options):
Add a new --config-file command line option that takes a single
argument.
(main):
Set the new fields of the serve_params_t to NULL.
If the --config-file option is used, then call load_configs().
]]]
Index: subversion/svnserve/serve.c
===================================================================
--- subversion/svnserve/serve.c (revision 24063)
+++ subversion/svnserve/serve.c (working copy)
@@ -76,6 +76,55 @@
apr_pool_t *pool; /* Pool provided in the handler call. */
} file_revs_baton_t;
+svn_error_t *load_configs(svn_config_t **cfg,
+ svn_config_t **pwdb,
+ svn_authz_t **authzdb,
+ const char *filename,
+ svn_boolean_t must_exist,
+ const char *base,
+ apr_pool_t *pool)
+{
+ const char *pwdb_path, *authzdb_path;
+ svn_error_t *err;
+
+ SVN_ERR(svn_config_read(cfg, filename, must_exist, pool));
+
+ svn_config_get(*cfg, &pwdb_path, SVN_CONFIG_SECTION_GENERAL,
+ SVN_CONFIG_OPTION_PASSWORD_DB, NULL);
+
+ *pwdb = NULL;
+ if (pwdb_path)
+ {
+ pwdb_path = svn_path_join(base, pwdb_path, pool);
+
+ /* Because it may be possible to read the pwdb file with some
+ * access methods and not others, ignore errors reading the pwdb
+ * file and just don't present password authentication as an
+ * option. TODO: Log a warning in this case, when we have a way
+ * of doing logging. */
+ err = svn_config_read(pwdb, pwdb_path, TRUE, pool);
+ if (err && err->apr_err == SVN_ERR_BAD_FILENAME)
+ svn_error_clear(err);
+ else if (err)
+ return err;
+ }
+
+ /* Read authz configuration. */
+ svn_config_get(*cfg, &authzdb_path, SVN_CONFIG_SECTION_GENERAL,
+ SVN_CONFIG_OPTION_AUTHZ_DB, NULL);
+ if (authzdb_path)
+ {
+ authzdb_path = svn_path_join(base, authzdb_path, pool);
+ SVN_ERR(svn_repos_authz_read(authzdb, authzdb_path, TRUE, pool));
+ }
+ else
+ {
+ *authzdb = NULL;
+ }
+
+ return SVN_NO_ERROR;
+}
+
/* Verify that URL is inside REPOS_URL and get its fs path. Assume that
REPOS_URL and URL are already URI-decoded. */
static svn_error_t *get_fs_path(const char *repos_url, const char *url,
@@ -2189,7 +2238,7 @@
static svn_error_t *find_repos(const char *url, const char *root,
server_baton_t *b, apr_pool_t *pool)
{
- const char *path, *full_path, *repos_root, *pwdb_path, *authz_path;
+ const char *path, *full_path, *repos_root;
svn_stringbuf_t *url_buf;
svn_error_t *err;
@@ -2233,30 +2282,13 @@
b->repos_url = url_buf->data;
b->authz_repos_name = svn_path_is_child(root, repos_root, pool);
- /* Read repository configuration. */
- SVN_ERR(svn_config_read(&b->cfg, svn_repos_svnserve_conf(b->repos, pool),
- FALSE, pool));
- svn_config_get(b->cfg, &pwdb_path, SVN_CONFIG_SECTION_GENERAL,
- SVN_CONFIG_OPTION_PASSWORD_DB, NULL);
-
- b->pwdb = NULL;
- b->realm = "";
- if (pwdb_path)
- {
- pwdb_path = svn_path_join(svn_repos_conf_dir(b->repos, pool),
- pwdb_path, pool);
-
- /* Because it may be possible to read the pwdb file with some
- * access methods and not others, ignore errors reading the
- * pwdb file and just don't present password authentication as
- * an option. TODO: Log a warning in this case, when we have a
- * way of doing logging. */
- err = svn_config_read(&b->pwdb, pwdb_path, TRUE, pool);
- if (err && err->apr_err == SVN_ERR_BAD_FILENAME)
- svn_error_clear(err);
- else if (err)
- return err;
- }
+ /* If the svnserve configuration files have not been loaded then
+ load them from the repository. */
+ if (NULL == b->cfg)
+ SVN_ERR(load_configs(&b->cfg, &b->pwdb, &b->authzdb,
+ svn_repos_svnserve_conf(b->repos, pool), FALSE,
+ svn_repos_conf_dir(b->repos, pool),
+ pool));
#ifdef SVN_HAVE_SASL
/* Should we use Cyrus SASL? */
@@ -2269,21 +2301,6 @@
svn_config_get(b->cfg, &b->realm, SVN_CONFIG_SECTION_GENERAL,
SVN_CONFIG_OPTION_REALM, b->realm);
- /* Read authz configuration. */
- svn_config_get(b->cfg, &authz_path, SVN_CONFIG_SECTION_GENERAL,
- SVN_CONFIG_OPTION_AUTHZ_DB, NULL);
- if (authz_path)
- {
- authz_path = svn_path_join(svn_repos_conf_dir(b->repos, pool),
- authz_path, pool);
- SVN_ERR(svn_repos_authz_read(&b->authzdb, authz_path,
- TRUE, pool));
- }
- else
- {
- b->authzdb = NULL;
- }
-
/* Make sure it's possible for the client to authenticate. Note
that this doesn't take into account any authz configuration read
above, because we can't know about access it grants until paths
@@ -2329,8 +2346,10 @@
b.tunnel_user = get_tunnel_user(params, pool);
b.read_only = params->read_only;
b.user = NULL;
- b.cfg = NULL; /* Ugly; can drop when we remove v1 support. */
- b.pwdb = NULL; /* Likewise */
+ b.cfg = params->cfg; /* Ugly; can drop when we remove v1 support. */
+ b.pwdb = params->pwdb; /* Likewise. */
+ b.authzdb = params->authzdb;
+ b.realm = NULL;
b.pool = pool;
/* Send greeting. When we drop support for version 1, we can
Index: subversion/svnserve/main.c
===================================================================
--- subversion/svnserve/main.c (revision 24063)
+++ subversion/svnserve/main.c (working copy)
@@ -135,6 +135,7 @@
#define SVNSERVE_OPT_VERSION 260
#define SVNSERVE_OPT_PID_FILE 261
#define SVNSERVE_OPT_SERVICE 262
+#define SVNSERVE_OPT_CONFIG_FILE 263
static const apr_getopt_option_t svnserve__options[] =
{
@@ -159,6 +160,8 @@
{"threads", 'T', 0, N_("use threads instead of fork")},
#endif
{"listen-once", 'X', 0, N_("listen once (useful for debugging)")},
+ {"config-file", SVNSERVE_OPT_CONFIG_FILE, 1,
+ N_("read configuration from file ARG")},
{"pid-file", SVNSERVE_OPT_PID_FILE, 1,
N_("write server process ID to file ARG")},
#ifdef WIN32
@@ -324,6 +327,7 @@
const char *host = NULL;
int family = APR_INET;
int mode_opt_count = 0;
+ const char *config_filename = NULL;
const char *pid_filename = NULL;
svn_node_kind_t kind;
@@ -366,6 +370,10 @@
params.tunnel = FALSE;
params.tunnel_user = NULL;
params.read_only = FALSE;
+ params.cfg = NULL;
+ params.pwdb = NULL;
+ params.authzdb = NULL;
+
while (1)
{
status = apr_getopt_long(os, svnserve__options, &opt, &arg);
@@ -474,6 +482,13 @@
break;
#endif
+ case SVNSERVE_OPT_CONFIG_FILE:
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&config_filename, arg, pool));
+ config_filename = svn_path_internal_style(config_filename, pool);
+ SVN_INT_ERR(svn_path_get_absolute(&config_filename, config_filename,
+ pool));
+ break;
+
case SVNSERVE_OPT_PID_FILE:
SVN_INT_ERR(svn_utf_cstring_to_utf8(&pid_filename, arg, pool));
pid_filename = svn_path_internal_style(pid_filename, pool);
@@ -494,6 +509,14 @@
usage(argv[0], pool);
}
+ /* If a configuration file is specified, load it and any referenced
+ * password and authorization files. */
+ if (config_filename)
+ SVN_INT_ERR(load_configs(¶ms.cfg, ¶ms.pwdb, ¶ms.authzdb,
+ config_filename, TRUE,
+ svn_path_dirname(config_filename, pool),
+ pool));
+
if (params.tunnel_user && run_mode != run_mode_tunnel)
{
svn_error_clear
Index: subversion/svnserve/server.h
===================================================================
--- subversion/svnserve/server.h (revision 24063)
+++ subversion/svnserve/server.h (working copy)
@@ -73,12 +73,44 @@
/* True if the read-only flag was specified on the command-line,
which forces all connections to be read-only. */
svn_boolean_t read_only;
+
+ /* A parsed repository svnserve configuration file, ala
+ svnserve.conf. If this is NULL, then no configuration file was
+ specified on the command line. If this is non-NULL, then
+ per-repository svnserve.conf are not read. */
+ svn_config_t *cfg;
+
+ /* A parsed repository password database. If this is NULL, then
+ either no svnserve configuration file was specified on the
+ command line, or it was specified and it did not refer to a
+ password database. */
+ svn_config_t *pwdb;
+
+ /* A parsed repository authorization database. If this is NULL,
+ then either no svnserve configuration file was specified on the
+ command line, or it was specified and it did not refer to a
+ authorization database. */
+ svn_authz_t *authzdb;
} serve_params_t;
/* Serve the connection CONN according to the parameters PARAMS. */
svn_error_t *serve(svn_ra_svn_conn_t *conn, serve_params_t *params,
apr_pool_t *pool);
+/* Load a svnserve configuration file located at FILENAME into CFG,
+ any referenced password database into PWDB and any referenced
+ authorization database into AUTHZDB. If MUST_EXIST is true and
+ FILENAME does not exist, then this returns an error. BASE may be
+ specified as the base path to any referenced password and
+ authorization files found in FILENAME. */
+svn_error_t *load_configs(svn_config_t **cfg,
+ svn_config_t **pwdb,
+ svn_authz_t **authzdb,
+ const char *filename,
+ svn_boolean_t must_exist,
+ const char *base,
+ apr_pool_t *pool);
+
/* Initialize the Cyrus SASL library. */
svn_error_t *cyrus_init(void);
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Sat Mar 24 01:04:15 2007