You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by br...@apache.org on 2013/01/03 09:19:37 UTC
svn commit: r1428209 - in /subversion/trunk: Makefile.in build.conf
build/win32/make_dist.py tools/server-side/svnauthz-validate.c
tools/server-side/svnauthz.c
Author: breser
Date: Thu Jan 3 08:19:36 2013
New Revision: 1428209
URL: http://svn.apache.org/viewvc?rev=1428209&view=rev
Log:
Rename svnauthz-validate to svnauthz and start using subcommands.
svnauthz now has a validate and accessof subcommands. If run with an argv[0]
that starts with 'svnauthz-validate' it enables a compat mode that behaves
almost exactly as svnauthz-validate did in 1.7. Only difference being that
it will accept file:// URLs. On UNIX we install a symlink as part of
the install-tools target now to make the old command work.
* Makefile.in
(INSTALL_EXTRA_TOOLS): symlink svnauthz-validate to svnauthz
* build/win32/make_dist.py
(_disttree): Rename svnauthz-validate.exe to svnauthz.exe
* build.conf
(__ALL__, svnauthz-validate, svnauthz): Rename svnauthz-validate to svnauthz
* tools/server-side/svnauthz-validate.c: Rename to ...
* tools/serverside/svnauthz.c
(svnauthz__cmdline_options_t): Replace an anonymous enum.
(options_table): Move options struct from sub_main().
(svnauthz_opt_state): typedef previous anonymous opts struct in sub_main().
(SVNAUTHZ_COMPAT_NAME): prefix of command name to enter compat mode.
(usage, subcommand_help): Replace usage() with subcommand_help().
(cmd_table): New struct for subcommands.
(get_authz, subcommand_validate, subcommand_accessof): New functions, split
off from sub_main().
(EXIT_FAILURE): Redefine to 2 to match our contract.
(handle_exit_error, EXIT_ERROR): Add exit_code argument.
(SVN_INT_ERR): Pass EXIT_FAILURE to EXIT_ERROR().
(use_compat_mode): New function.
(sub_main): Refactor to use subcommands and support compat mode.
(main): Use EXIT_FAILURE instead of hardcoded 2.
Added:
subversion/trunk/tools/server-side/svnauthz.c
- copied, changed from r1427958, subversion/trunk/tools/server-side/svnauthz-validate.c
Removed:
subversion/trunk/tools/server-side/svnauthz-validate.c
Modified:
subversion/trunk/Makefile.in
subversion/trunk/build.conf
subversion/trunk/build/win32/make_dist.py
Modified: subversion/trunk/Makefile.in
URL: http://svn.apache.org/viewvc/subversion/trunk/Makefile.in?rev=1428209&r1=1428208&r2=1428209&view=diff
==============================================================================
--- subversion/trunk/Makefile.in (original)
+++ subversion/trunk/Makefile.in Thu Jan 3 08:19:36 2013
@@ -926,4 +926,5 @@ INSTALL_EXTRA_TOOLS=\
$(MKDIR) $(DESTDIR)$(bindir); \
test -n "$$SVN_SVNMUCC_IS_SVNSYITF" && \
ln -sf svnmucc$(EXEEXT) $(DESTDIR)$(bindir)/svnsyitf$(EXEEXT); \
- ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT)
+ ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \
+ ln -sf $(DESTDIR)$(toolsdir)/svnauthz$(EXEEXT) $(DESTDIR)$(toolsdir)/svnauthz-validate
Modified: subversion/trunk/build.conf
URL: http://svn.apache.org/viewvc/subversion/trunk/build.conf?rev=1428209&r1=1428208&r2=1428209&view=diff
==============================================================================
--- subversion/trunk/build.conf (original)
+++ subversion/trunk/build.conf Thu Jan 3 08:19:36 2013
@@ -1204,7 +1204,7 @@ path = build/win32
libs = svn svnadmin svndumpfilter svnlook svnmucc svnserve svnrdump svnsync
svnversion
mod_authz_svn mod_dav_svn mod_dontdothat
- svnauthz-validate svnraisetreeconflict
+ svnauthz svnraisetreeconflict
[__ALL_TESTS__]
type = project
@@ -1322,11 +1322,11 @@ install = tools
libs = libsvn_client libsvn_wc libsvn_ra libsvn_subr libsvn_delta
apriconv apr
-[svnauthz-validate]
-description = Authz config file validator
+[svnauthz]
+description = Authz config file tool
type = exe
path = tools/server-side
-sources = svnauthz-validate.c
+sources = svnauthz.c
install = tools
libs = libsvn_repos libsvn_fs libsvn_subr apr
Modified: subversion/trunk/build/win32/make_dist.py
URL: http://svn.apache.org/viewvc/subversion/trunk/build/win32/make_dist.py?rev=1428209&r1=1428208&r2=1428209&view=diff
==============================================================================
--- subversion/trunk/build/win32/make_dist.py (original)
+++ subversion/trunk/build/win32/make_dist.py Thu Jan 3 08:19:36 2013
@@ -215,8 +215,8 @@ _disttree = {'': OptFile('%(readme)s', '
File('%(blddir)s/svnmucc/svnmucc.pdb'),
File('%(blddir)s/../contrib/client-side/svn-push/svn-push.exe'),
File('%(blddir)s/../contrib/client-side/svn-push/svn-push.pdb'),
- File('%(blddir)s/../tools/server-side/svnauthz-validate.exe'),
- File('%(blddir)s/../tools/server-side/svnauthz-validate.pdb'),
+ File('%(blddir)s/../tools/server-side/svnauthz.exe'),
+ File('%(blddir)s/../tools/server-side/svnauthz.pdb'),
File('%(blddir)s/../tools/server-side/svn-populate-node-origins-index.exe'),
File('%(blddir)s/../tools/server-side/svn-populate-node-origins-index.pdb'),
File('%(blddir)s/../tools/dev/svnraisetreeconflict/svnraisetreeconflict.exe'),
Copied: subversion/trunk/tools/server-side/svnauthz.c (from r1427958, subversion/trunk/tools/server-side/svnauthz-validate.c)
URL: http://svn.apache.org/viewvc/subversion/trunk/tools/server-side/svnauthz.c?p2=subversion/trunk/tools/server-side/svnauthz.c&p1=subversion/trunk/tools/server-side/svnauthz-validate.c&r1=1427958&r2=1428209&rev=1428209&view=diff
==============================================================================
--- subversion/trunk/tools/server-side/svnauthz-validate.c (original)
+++ subversion/trunk/tools/server-side/svnauthz.c Thu Jan 3 08:19:36 2013
@@ -1,5 +1,5 @@
/*
- * svnauthz-validate.c : Load and validate an authz file.
+ * svnauthz.c : Tool for working with authz files.
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,13 +19,6 @@
* specific language governing permissions and limitations
* under the License.
* ====================================================================
- *
- *
- * svnauthz-validate.c : load and validate an authz file, returns
- * value == 0 if syntax of authz file is correct
- * value == 1 if syntax of authz file is invalid or file not found
- * value == 2 in case of general error
- *
*/
#include "svn_cmdline.h"
@@ -36,34 +29,134 @@
#include "svn_utf.h"
#include "svn_path.h"
-enum {
- OPT_USERNAME = SVN_OPT_FIRST_LONGOPT_ID,
- OPT_PATH,
- OPT_REPOS
+
+/*** Option Processing. ***/
+
+enum svnauthz__cmdline_options_t
+{
+ svnauthz__version = SVN_OPT_FIRST_LONGOPT_ID,
+ svnauthz__username,
+ svnauthz__path,
+ svnauthz__repos
};
-static int
-usage(const char *argv0)
+/* Option codes and descriptions.
+ *
+ * The entire list must be terminated with an entry of nulls.
+ */
+static const apr_getopt_option_t options_table[] =
+{
+ {"help", 'h', 0, ("show help on a subcommand")},
+ {NULL, '?', 0, ("show help on a subcommand")},
+ {"version", svnauthz__version, 0, ("show program version information")},
+ {"username", svnauthz__username, 1, ("username to check access of")},
+ {"path", svnauthz__path, 1, ("path within repository to check access of")},
+ {"repository", svnauthz__repos, 1, ("repository authz name")},
+ {"transaction", 't', 1, ("transaction id")},
+ {0, 0, 0, 0}
+};
+
+struct svnauthz_opt_state
+{
+ svn_boolean_t help;
+ svn_boolean_t version;
+ const char *authz_file;
+ const char *username;
+ const char *fspath;
+ const char *repos_name;
+ const char *txn;
+ const char *repos_path;
+};
+
+#define SVNAUTHZ_COMPAT_NAME "svnauthz-validate"
+
+
+
+/*** Subcommands. */
+
+static svn_opt_subcommand_t
+ subcommand_help,
+ subcommand_validate,
+ subcommand_accessof;
+
+/* Array of available subcommands.
+ * The entire list must be terminated with an entry of nulls.
+ */
+static const svn_opt_subcommand_desc2_t cmd_table[] =
+{
+ {"help", subcommand_help, {"?", "h"},
+ ("usage: svnauthz help [SUBCOMMAND...]\n\n"
+ "Describe the usage of this program or its subcommands.\n"),
+ {0} },
+ {"validate", subcommand_validate, {0} /* no aliases */,
+ ("Checks the syntax of an authz file.\n"
+ "usage: 1. svnauthz validate TARGET\n"
+ " 2. svnauthz validate --transaction TXN REPOS_PATH FILE_PATH\n\n"
+ " 1. Loads and validates the syntax of the authz file at TARGET.\n"
+ " TARGET can be a path to a file or an absolute file:// URL to an authz\n"
+ " file in a repository, but cannot be a repository relative URL (^/).\n\n"
+ " 2. Loads and validates the syntax of the authz file at FILE_PATH in the\n"
+ " transaction TXN in the repository at REPOS_PATH.\n\n"
+ "Returns:\n"
+ " 0 when syntax is OK.\n"
+ " 1 when syntax is invalid.\n"
+ " 2 operational error\n"
+ ),
+ {'t'} },
+ {"accessof", subcommand_accessof, {0} /* no aliases */,
+ ("Output the permissions set by an authz file for a specific circumstance.\n"
+ "usage: 1. svnauthz accessof [--username USER] TARGET\n"
+ " 2. svnauthz accessof [--username USER] -t TXN REPOS_PATH FILE_PATH\n\n"
+ " 1. Prints the access of USER based on TARGET.\n"
+ " TARGET can be a path to a file or an absolute file:// URL to an authz\n"
+ " file in a repository, but cannot be a repository relative URL (^/).\n\n"
+ " 2. Prints the access of USER based on authz file at FILE_PATH in the\n"
+ " transaction TXN in the repository at REPOS_PATH.\n\n"
+ " If the --username argument is ommitted then access of an anonymous user\n"
+ " will be printed. If --path argument is ommitted prints if any access\n"
+ " to the repo is allowed.\n\n"
+ "Outputs one of the following:\n"
+ " rw write access (which also implies read)\n"
+ " r read access\n"
+ " no no access\n\n"
+ "Returns:\n"
+ " 0 when syntax is OK.\n"
+ " 1 when syntax is invalid.\n"
+ " 2 operational error\n"
+ ),
+ {'t', svnauthz__username, svnauthz__path, svnauthz__repos} },
+};
+
+static svn_error_t *
+subcommand_help(apr_getopt_t *os, void *baton, apr_pool_t *pool)
{
- printf("Usage: 1. %s [OPTION]... TARGET\n", argv0);
- printf(" 2. %s [OPTION]... --transaction TXN REPOS_PATH FILE_PATH\n\n", argv0);
- printf(" 1. Loads and validates the syntax of the authz file at TARGET.\n"
- " TARGET can be a path to a file or an absolute file:// URL to an authz\n"
- " file in a repository, but cannot be a repository relative URL (^/).\n\n"
- " 2. Loads and validates the syntax of the authz file at FILE_PATH in the\n"
- " transaction TXN in the repository at REPOS_PATH.\n\n"
- " Options:\n\n"
- " --username USER : prints access available for a user\n"
- " --path FSPATH : makes --username print access available for FSPATH\n"
- " --repository REPOS_NAME : use REPOS_NAME as repository authz name when\n"
- " determining access available with --username\n"
- " -t, --transaction TXN : enables mode 2 which looks for the file in an\n"
- " uncommitted transaction TXN\n\n"
- "Returns:\n"
- " 0 when syntax is OK.\n"
- " 1 when syntax is invalid.\n"
- " 2 operational error\n");
- return 2;
+ struct svnauthz_opt_state *opt_state = baton;
+ const char *header =
+ ("general usage: svnauthz SUBCOMMAND TARGET [ARGS & OPTIONS ...]\n"
+ " " SVNAUTHZ_COMPAT_NAME " TARGET\n\n"
+ "If the filename for the command starts with '" SVNAUTHZ_COMPAT_NAME "', runs in\n"
+ "pre 1.8 compatability mode; which runs the validate subcommand on TARGET.\n\n"
+ "Type 'svnauthz help <subcommand>' for help on a specific subcommand.\n"
+ "Type 'svnauthz --version' to see the program version.\n\n"
+ "Available subcommands:\n");
+
+ const char *fs_desc_start
+ = ("The following repository back-end (FS) modules are available:\n\n");
+
+ svn_stringbuf_t *version_footer;
+
+ version_footer = svn_stringbuf_create(fs_desc_start, pool);
+ SVN_ERR(svn_fs_print_modules(version_footer, pool));
+
+ SVN_ERR(svn_opt_print_help4(os, "svnauthz",
+ opt_state ? opt_state->version : FALSE,
+ FALSE, /* quiet */
+ FALSE, /* verbose */
+ version_footer->data,
+ header, cmd_table, options_table, NULL, NULL,
+ pool));
+
+ return SVN_NO_ERROR;
}
/* Loads the authz config into *AUTHZ from the file at AUTHZ_FILE
@@ -105,13 +198,78 @@ get_authz_from_txn(svn_authz_t **authz,
return SVN_NO_ERROR;
}
-/* Similar to svn_cmdline_handle_exit_error but returns 2 rather than
- EXIT_FAILURE since our contract demands that we exit with 2 for
- internal failures. Also is missing the pool argument since we
- don't need it given main/sub_main. */
+/* Loads the authz config into *AUTHZ from OPT_STATE->AUTHZ_FILE. If
+ OPT_STATE->TXN is set then OPT_STATE->AUTHZ_FILE is treated as a fspath
+ in repository at OPT_STATE->REPOS_PATH. */
+static svn_error_t *
+get_authz(svn_authz_t **authz, struct svnauthz_opt_state *opt_state,
+ apr_pool_t *pool)
+{
+ /* Read the access file and validate it. */
+ if (opt_state->txn)
+ return get_authz_from_txn(authz, opt_state->repos_path,
+ opt_state->authz_file, opt_state->txn, pool);
+
+ /* Else */
+ return svn_repos_authz_read2(authz, opt_state->authz_file, TRUE, NULL, pool);
+}
+
+static svn_error_t *
+subcommand_validate(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ struct svnauthz_opt_state *opt_state = baton;
+ svn_authz_t *authz;
+
+ /* Not much to do here since just loading the authz file also validates. */
+ return get_authz(&authz, opt_state, pool);
+}
+
+static svn_error_t *
+subcommand_accessof(apr_getopt_t *os, void *baton, apr_pool_t *pool)
+{
+ svn_authz_t *authz;
+ svn_boolean_t read_access, write_access;
+ svn_error_t *err;
+ struct svnauthz_opt_state *opt_state = baton;
+ const char *user = opt_state->username;
+ const char *path = opt_state->fspath;
+ const char *repos = opt_state->repos_name;
+
+ SVN_ERR(get_authz(&authz, opt_state, pool));
+
+ if (path && path[0] != '/')
+ path = apr_pstrcat(pool, "/", path, NULL);
+
+ err = svn_repos_authz_check_access(authz, repos, path, user,
+ svn_authz_write, &write_access,
+ pool);
+ if (!write_access && !err)
+ err = svn_repos_authz_check_access(authz, repos, path, user,
+ svn_authz_read, &read_access,
+ pool);
+ if (!err)
+ printf("%s\n",
+ write_access ? "rw" : read_access ? "r" : "no"
+ );
+
+ return err;
+}
+
+
+
+/*** Main. ***/
+
+/* A redefinition of EXIT_FAILURE since our contract demands that we
+ exit with 2 for internal failures. */
+#undef EXIT_FAILURE
+#define EXIT_FAILURE 2
+
+/* Similar to svn_cmdline_handle_exit_error but with an exit_code argument
+ so we can comply with our contract an exit with 2 for internal failures.
+ Also is missing the pool argument since we don't need it given
+ main/sub_main. */
static int
-handle_exit_error(svn_error_t *err,
- const char *prefix)
+handle_exit_error(svn_error_t *err, const char *prefix, int exit_code)
{
/* Issue #3014:
* Don't print anything on broken pipes. The pipe was likely
@@ -123,174 +281,286 @@ handle_exit_error(svn_error_t *err,
if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
svn_handle_error2(err, stderr, FALSE, prefix);
svn_error_clear(err);
- return 2;
+ return exit_code;
}
/* Report and clear the error ERR, and return EXIT_FAILURE. */
-#define EXIT_ERROR(err) \
- handle_exit_error(err, "svnauthz-validate: ")
+#define EXIT_ERROR(err, exit_code) \
+ handle_exit_error(err, "svnauthz: ", exit_code)
/* A redefinition of the public SVN_INT_ERR macro, that suppresses the
* error message if it is SVN_ERR_IO_PIPE_WRITE_ERROR, amd with the
- * program name 'svnauthz-validate' instead of 'svn'. */
+ * program name 'svnauthz' instead of 'svn'. */
#undef SVN_INT_ERR
#define SVN_INT_ERR(expr) \
do { \
svn_error_t *svn_err__temp = (expr); \
if (svn_err__temp) \
- return EXIT_ERROR(svn_err__temp); \
+ return EXIT_ERROR(svn_err__temp, EXIT_FAILURE); \
} while (0)
+static svn_boolean_t
+use_compat_mode(const char *cmd, apr_pool_t *pool)
+{
+ cmd = svn_dirent_internal_style(cmd, pool);
+ cmd = svn_dirent_basename(cmd, NULL);
+
+ /* Deliberately look only for the start of the name to deal with
+ the executable extension on some platforms. */
+ return 0 == strncmp(SVNAUTHZ_COMPAT_NAME, cmd,
+ strlen(SVNAUTHZ_COMPAT_NAME));
+}
+
static int
sub_main(int argc, const char *argv[], apr_pool_t *pool)
{
svn_error_t *err;
- apr_status_t apr_err;
- svn_authz_t *authz;
+
+ const svn_opt_subcommand_desc2_t *subcommand = NULL;
+ struct svnauthz_opt_state opt_state = { 0 };
apr_getopt_t *os;
- const apr_getopt_option_t options[] =
- {
- {"username", OPT_USERNAME, 1, ("the authenticated username")},
- {"path", OPT_PATH, 1, ("path within the repository")},
- {"repository", OPT_REPOS, 1, ("repository authz name")},
- {"transaction", 't', 1, ("transaction id")},
- {0, 0, 0, 0}
- };
- struct {
- const char *authz_file;
- const char *username;
- const char *fspath;
- const char *repos_name;
- const char *txn;
- const char *repos_path;
- } opts;
- opts.username = opts.fspath = opts.repos_name = opts.txn = NULL;
- opts.repos_path = NULL;
+ apr_array_header_t *received_opts;
+ int i;
/* Initialize the FS library. */
SVN_INT_ERR(svn_fs_initialize(pool));
- /* Repeat svn_cmdline__getopt_init() inline. */
- apr_err = apr_getopt_init(&os, pool, argc, argv);
- if (apr_err)
+ received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));
+
+ /* Initialize opt_state */
+ opt_state.username = opt_state.fspath = opt_state.repos_name = NULL;
+ opt_state.txn = opt_state.repos_path = NULL;
+
+ /* Parse options. */
+ SVN_INT_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));
+ os->interleave = 1;
+
+ if (!use_compat_mode(argv[0], pool))
+ {
+ while (1)
+ {
+ int opt;
+ const char *arg;
+ apr_status_t status = apr_getopt_long(os, options_table, &opt, &arg);
+
+ if (APR_STATUS_IS_EOF(status))
+ break;
+ if (status != APR_SUCCESS)
+ {
+ SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+ return EXIT_FAILURE;
+ }
+
+ /* Stash the option code in an array before parsing it. */
+ APR_ARRAY_PUSH(received_opts, int) = opt;
+
+ switch (opt)
+ {
+ case 'h':
+ case '?':
+ opt_state.help = TRUE;
+ break;
+ case 't':
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.txn, arg, pool));
+ break;
+ case svnauthz__version:
+ opt_state.version = TRUE;
+ break;
+ case svnauthz__username:
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.username, arg, pool));
+ break;
+ case svnauthz__path:
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.fspath, arg, pool));
+ break;
+ case svnauthz__repos:
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.repos_name, arg, pool));
+ break;
+ default:
+ {
+ SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+ return EXIT_FAILURE;
+ }
+ }
+ }
+ }
+ else
{
- err = svn_error_wrap_apr(apr_err,
- ("Error initializing command line arguments"));
- svn_handle_warning2(stderr, err, "svnauthz-validate: ");
- return 2;
+ /* Pre 1.8 compatability mode. */
+ if (argc == 1) /* No path argument */
+ subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help");
+ else
+ subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "validate");
}
- os->interleave = 1;
- while (1)
+ /* If the user asked for help, then the rest of the arguments are
+ the names of subcommands to get help on (if any), or else they're
+ just typos/mistakes. Whatever the case, the subcommand to
+ actually run is subcommand_help(). */
+ if (opt_state.help)
+ subcommand = svn_opt_get_canonical_subcommand2(cmd_table, "help");
+
+ if (subcommand == NULL)
{
- int opt;
- const char *arg;
- apr_status_t status = apr_getopt_long(os, options, &opt, &arg);
- if (APR_STATUS_IS_EOF(status))
- break;
- if (status != APR_SUCCESS)
- {
- return usage(argv[0]);
- }
- switch (opt)
- {
- case OPT_USERNAME:
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.username, arg, pool));
- break;
- case OPT_PATH:
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.fspath, arg, pool));
- break;
- case OPT_REPOS:
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.repos_name, arg, pool));
- break;
- case 't':
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.txn, arg, pool));
- break;
- default:
- return usage(argv[0]);
+ if (os->ind >= os->argc)
+ {
+ if (opt_state.version)
+ {
+ /* Use the "help" subcommand to handle the "--version" option. */
+ static const svn_opt_subcommand_desc2_t pseudo_cmd =
+ { "--version", subcommand_help, {0}, "",
+ {svnauthz__version /* must accept its own option */ } };
+
+ subcommand = &pseudo_cmd;
+ }
+ else
+ {
+ svn_error_clear(svn_cmdline_fprintf(stderr, pool,
+ ("subcommand argument required\n")));
+ SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+ return EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ const char *first_arg = os->argv[os->ind++];
+ subcommand = svn_opt_get_canonical_subcommand2(cmd_table, first_arg);
+ if (subcommand == NULL)
+ {
+ const char *first_arg_utf8;
+
+ os->ind++;
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&first_arg_utf8,
+ first_arg, pool));
+ svn_error_clear(svn_cmdline_fprintf(stderr, pool,
+ ("Unknown command: '%s'\n"),
+ first_arg_utf8));
+ SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+ return EXIT_FAILURE;
+ }
}
}
- /* Consume a non-option argument (repos_path) if --transaction */
- if (opts.txn)
+ /* Every subcommand except `help' requires one or two non-option arguments.
+ Parse them and store them in opt_state.*/
+ if (subcommand->cmd_func != subcommand_help)
{
- if (os->ind +2 != argc)
- return usage(argv[0]);
+ /* Consume a non-option argument (repos_path) if --transaction */
+ if (opt_state.txn)
+ {
+ if (os->ind +2 != argc)
+ {
+ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ ("Repository and authz file arguments "
+ "required"));
+ return EXIT_ERROR(err, EXIT_FAILURE);
+ }
+
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.repos_path, os->argv[os->ind],
+ pool));
+ os->ind++;
+
+ opt_state.repos_path = svn_dirent_internal_style(opt_state.repos_path, pool);
+ }
+
+ /* Exactly 1 non-option argument */
+ if (os->ind + 1 != argc)
+ {
+ err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ ("Authz file argument required"));
+ return EXIT_ERROR(err, EXIT_FAILURE);
+ }
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.repos_path, os->argv[os->ind],
+ /* Grab AUTHZ_FILE from argv. */
+ SVN_INT_ERR(svn_utf_cstring_to_utf8(&opt_state.authz_file, os->argv[os->ind],
pool));
- os->ind++;
- opts.repos_path = svn_dirent_internal_style(opts.repos_path, pool);
+ /* Can't accept repos relative urls since we don't have the path to the
+ * repository and URLs don't need to be converted to internal style. */
+ if (svn_path_is_repos_relative_url(opt_state.authz_file))
+ {
+ err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ ("'%s' is a repository relative URL when it "
+ "should be a local path or file:// URL"),
+ opt_state.authz_file);
+ return EXIT_ERROR(err, EXIT_FAILURE);
+ }
+ else if (!svn_path_is_url(opt_state.authz_file))
+ opt_state.authz_file = svn_dirent_internal_style(opt_state.authz_file, pool);
+ else if (opt_state.txn) /* don't allow urls with transaction argument */
+ {
+ err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
+ ("'%s' is a URL when it should be a "
+ "local path"), opt_state.authz_file);
+ return EXIT_ERROR(err, EXIT_FAILURE);
+ }
}
- /* Exactly 1 non-option argument, and no --repository/--path
- unless --username. */
- if (os->ind + 1 != argc || (!opts.username && (opts.fspath || opts.repos_name)))
+ /* Check that the subcommand wasn't passed any inappropriate options. */
+ for (i = 0; i < received_opts->nelts; i++)
{
- return usage(argv[0]);
- }
+ int opt_id = APR_ARRAY_IDX(received_opts, i, int);
- /* Grab AUTHZ_FILE from argv. */
- SVN_INT_ERR(svn_utf_cstring_to_utf8(&opts.authz_file, os->argv[os->ind],
- pool));
-
- /* Can't accept repos relative urls since we don't have the path to the
- * repository and URLs don't need to be converted to internal style. */
- if (svn_path_is_repos_relative_url(opts.authz_file))
- return usage(argv[0]);
- else if (!svn_path_is_url(opts.authz_file))
- opts.authz_file = svn_dirent_internal_style(opts.authz_file, pool);
- else if (opts.txn) /* don't allow urls with transaction argument */
- return usage(argv[0]);
+ /* All commands implicitly accept --help, so just skip over this
+ when we see it. Note that we don't want to include this option
+ in their "accepted options" list because it would be awfully
+ redundant to display it in every commands' help text. */
+ if (opt_id == 'h' || opt_id == '?')
+ continue;
- /* Read the access file and validate it. */
- if (opts.txn)
- {
- err = get_authz_from_txn(&authz, opts.repos_path,
- opts.authz_file, opts.txn, pool);
- }
- else
- {
- err = svn_repos_authz_read2(&authz, opts.authz_file, TRUE, NULL, pool);
+ if (! svn_opt_subcommand_takes_option3(subcommand, opt_id, NULL))
+ {
+ const char *optstr;
+ const apr_getopt_option_t *badopt =
+ svn_opt_get_option_from_code2(opt_id, options_table, subcommand,
+ pool);
+ svn_opt_format_option(&optstr, badopt, FALSE, pool);
+ if (subcommand->name[0] == '-')
+ SVN_INT_ERR(subcommand_help(NULL, NULL, pool));
+ else
+ svn_error_clear(svn_cmdline_fprintf(stderr, pool,
+ ("Subcommand '%s' doesn't accept option '%s'\n"
+ "Type 'svnauthz help %s' for usage.\n"),
+ subcommand->name, optstr, subcommand->name));
+ return EXIT_FAILURE;
+ }
}
- /* Optionally, print the access a USER has to a given PATH in REPOS.
- PATH and REPOS may be NULL. */
- if (!err && opts.username)
- {
- const char *user = opts.username;
- const char *path = opts.fspath;
- const char *repos = opts.repos_name;
- svn_boolean_t read_access, write_access;
-
- if (path && path[0] != '/')
- path = apr_pstrcat(pool, "/", path, NULL);
-
- err = svn_repos_authz_check_access(authz, repos, path, user,
- svn_authz_write, &write_access,
- pool);
- if (!write_access && !err)
- err = svn_repos_authz_check_access(authz, repos, path, user,
- svn_authz_read, &read_access,
- pool);
- if (!err)
- printf("%s\n",
- write_access ? "rw" : read_access ? "r" : "no"
- );
- }
+ /* Run the subcommand. */
+ err = (*subcommand->cmd_func)(os, &opt_state, pool);
if (err)
{
- svn_handle_error2(err, stderr, FALSE, "svnauthz-validate: ");
- svn_error_clear(err);
- return 1;
+ if (err->apr_err == SVN_ERR_CL_INSUFFICIENT_ARGS
+ || err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR)
+ {
+ /* For argument-related problems, suggest using the 'help'
+ subcommand. */
+ err = svn_error_quick_wrap(err,
+ ("Try 'svnauthz help' for more info"));
+ }
+ else if (err->apr_err == SVN_ERR_AUTHZ_INVALID_CONFIG
+ || err->apr_err == SVN_ERR_MALFORMED_FILE)
+ {
+ /* Follow our contract that says we exit with 1 if the file does not
+ validate. */
+ return EXIT_ERROR(err, 1);
+ }
+
+ return EXIT_ERROR(err, EXIT_FAILURE);
}
else
{
- return 0;
+ /* Ensure that everything is written to stdout, so the user will
+ see any print errors. */
+ err = svn_cmdline_fflush(stdout);
+ if (err)
+ {
+ return EXIT_ERROR(err, EXIT_FAILURE);
+ }
+ return EXIT_SUCCESS;
}
+
}
int
@@ -301,7 +571,7 @@ main(int argc, const char *argv[])
/* Initialize the app. Send all error messages to 'stderr'. */
if (svn_cmdline_init(argv[0], stderr) != EXIT_SUCCESS)
- return 2;
+ return EXIT_FAILURE;
pool = svn_pool_create(NULL);
Re: svn commit: r1428209 - in /subversion/trunk: Makefile.in
build.conf build/win32/make_dist.py tools/server-side/svnauthz-validate.c tools/server-side/svnauthz.c
Posted by Ben Reser <be...@reser.org>.
On Thu, Jan 3, 2013 at 2:46 PM, Daniel Shahaf <da...@elego.de> wrote:
> Use a relative target for the symlink?
>
> For svnmucc I couldn't do this because bindir != toolsdir, but that
> consideration doesn't kick in for svnauthz.
Done in r1428712.
Re: svn commit: r1428209 - in /subversion/trunk: Makefile.in
build.conf build/win32/make_dist.py tools/server-side/svnauthz-validate.c tools/server-side/svnauthz.c
Posted by Ben Reser <be...@reser.org>.
On Thu, Jan 3, 2013 at 2:46 PM, Daniel Shahaf <da...@elego.de> wrote:
> Use a relative target for the symlink?
>
> For svnmucc I couldn't do this because bindir != toolsdir, but that
> consideration doesn't kick in for svnauthz.
Done in r1428712.
Re: svn commit: r1428209 - in /subversion/trunk: Makefile.in
build.conf build/win32/make_dist.py
tools/server-side/svnauthz-validate.c tools/server-side/svnauthz.c
Posted by Daniel Shahaf <da...@elego.de>.
breser@apache.org wrote on Thu, Jan 03, 2013 at 08:19:37 -0000:
> @@ -926,4 +926,5 @@ INSTALL_EXTRA_TOOLS=\
> $(MKDIR) $(DESTDIR)$(bindir); \
> test -n "$$SVN_SVNMUCC_IS_SVNSYITF" && \
> ln -sf svnmucc$(EXEEXT) $(DESTDIR)$(bindir)/svnsyitf$(EXEEXT); \
> - ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT)
> + ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \
> + ln -sf $(DESTDIR)$(toolsdir)/svnauthz$(EXEEXT) $(DESTDIR)$(toolsdir)/svnauthz-validate
Use a relative target for the symlink?
For svnmucc I couldn't do this because bindir != toolsdir, but that
consideration doesn't kick in for svnauthz.
Thanks!
Daniel
Re: svn commit: r1428209 - in /subversion/trunk: Makefile.in
build.conf build/win32/make_dist.py
tools/server-side/svnauthz-validate.c tools/server-side/svnauthz.c
Posted by Daniel Shahaf <da...@elego.de>.
breser@apache.org wrote on Thu, Jan 03, 2013 at 08:19:37 -0000:
> @@ -926,4 +926,5 @@ INSTALL_EXTRA_TOOLS=\
> $(MKDIR) $(DESTDIR)$(bindir); \
> test -n "$$SVN_SVNMUCC_IS_SVNSYITF" && \
> ln -sf svnmucc$(EXEEXT) $(DESTDIR)$(bindir)/svnsyitf$(EXEEXT); \
> - ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT)
> + ln -sf $(DESTDIR)$(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \
> + ln -sf $(DESTDIR)$(toolsdir)/svnauthz$(EXEEXT) $(DESTDIR)$(toolsdir)/svnauthz-validate
Use a relative target for the symlink?
For svnmucc I couldn't do this because bindir != toolsdir, but that
consideration doesn't kick in for svnauthz.
Thanks!
Daniel