Example #1
0
static void
print_error(svn_error_t *err, FILE *stream, const char *prefix)
{
  char errbuf[256];
  const char *err_string;
  svn_error_t *temp_err = NULL;  /* ensure initialized even if
                                    err->file == NULL */
  /* Pretty-print the error */
  /* Note: we can also log errors here someday. */

#ifdef SVN_DEBUG
  /* Note: err->file is _not_ in UTF-8, because it's expanded from
           the __FILE__ preprocessor macro. */
  const char *file_utf8;

  if (err->file
      && !(temp_err = svn_utf_cstring_to_utf8(&file_utf8, err->file,
                                              err->pool)))
    svn_error_clear(svn_cmdline_fprintf(stream, err->pool,
                                        "%s:%ld", err->file, err->line));
  else
    {
      svn_error_clear(svn_cmdline_fputs(SVN_FILE_LINE_UNDEFINED,
                                        stream, err->pool));
      svn_error_clear(temp_err);
    }

  svn_error_clear(svn_cmdline_fprintf(stream, err->pool,
                                      ": (apr_err=%d)\n", err->apr_err));
#endif /* SVN_DEBUG */

  /* Only print the same APR error string once. */
  if (err->message)
    {
      svn_error_clear(svn_cmdline_fprintf(stream, err->pool, "%s%s\n",
                                          prefix, err->message));
    }
  else
    {
      /* Is this a Subversion-specific error code? */
      if ((err->apr_err > APR_OS_START_USEERR)
          && (err->apr_err <= APR_OS_START_CANONERR))
        err_string = svn_strerror(err->apr_err, errbuf, sizeof(errbuf));
      /* Otherwise, this must be an APR error code. */
      else if ((temp_err = svn_utf_cstring_to_utf8
                (&err_string, apr_strerror(err->apr_err, errbuf,
                                           sizeof(errbuf)), err->pool)))
        {
          svn_error_clear(temp_err);
          err_string = _("Can't recode error string from APR");
        }

      svn_error_clear(svn_cmdline_fprintf(stream, err->pool,
                                          "%s%s\n", prefix, err_string));
    }
}
Example #2
0
static int
l_propset (lua_State *L) {

	const char *path = luaL_checkstring (L, 1);
	const char *propname = luaL_checkstring (L, 2);
	const char *propval = lua_isnil (L, 3) ? NULL : luaL_checkstring (L, 3);
	
	apr_pool_t *pool;
	svn_error_t *err;
	svn_client_ctx_t *ctx;

	init_function (&ctx, &pool, L);

	path = svn_path_canonicalize (path, pool);

	const char *propname_utf8;
	err = svn_utf_cstring_to_utf8 (&propname_utf8, propname, pool);
	IF_ERROR_RETURN (err, pool, L);

	if (propval != NULL) {
		svn_string_t *sstring = svn_string_create (propval, pool);

		err = svn_client_propset2 (propname_utf8, sstring, path, TRUE, FALSE, ctx, pool);
	} else {
		err = svn_client_propset2 (propname_utf8, NULL, path, TRUE, FALSE, ctx, pool);
	}
	IF_ERROR_RETURN (err, pool, L);
	
	svn_pool_destroy (pool);

	return 0;

}
Example #3
0
File: main.c Project: ejrh/ejrh
/* Helper to parse local repository path.  Try parsing next parameter
 * of OS as a local path to repository.  If successfull *REPOS_PATH
 * will contain internal style path to the repository.
 */
static svn_error_t *
parse_local_repos_path (apr_getopt_t *os, 
                        const char ** repos_path, 
                        apr_pool_t *pool)
{
  *repos_path = NULL;

  /* Check to see if there is one more parameter. */
  if (os->ind < os->argc)
    {
      const char * path = os->argv[os->ind++];
      SVN_ERR (svn_utf_cstring_to_utf8 (repos_path, path, pool));
      *repos_path = svn_path_internal_style (*repos_path, pool);
    }

  if (*repos_path == NULL)
    {
      return svn_error_create (SVN_ERR_CL_ARG_PARSING_ERROR, NULL, 
                               _("Repository argument required"));
    }
  else if (svn_path_is_url (*repos_path))
    {
      return svn_error_createf (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("'%s' is an URL when it should be a path"),
                                *repos_path);
    }

  return SVN_NO_ERROR;   
}
Example #4
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__changelist(apr_getopt_t *os,
                   void *baton,
                   apr_pool_t *pool)
{
  const char *changelist_name = NULL;
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  apr_array_header_t *targets;
  svn_depth_t depth = opt_state->depth;

  /* If we're not removing changelists, then our first argument should
     be the name of a changelist. */

  if (! opt_state->remove)
    {
      apr_array_header_t *args;
      SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
      changelist_name = APR_ARRAY_IDX(args, 0, const char *);
      if (changelist_name[0] == '\0')
        return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                _("Changelist names must not be empty"));
      SVN_ERR(svn_utf_cstring_to_utf8(&changelist_name,
                                      changelist_name, pool));
    }
Example #5
0
/* Helper function.  Set URL to a "file://" url for the current directory,
   suffixed by the forward-slash-style relative path SUFFIX, performing all
   allocation in POOL. */
static svn_error_t *
current_directory_url(const char **url,
                      const char *suffix,
                      apr_pool_t *pool)
{
  /* 8KB is a lot, but it almost guarantees that any path will fit. */
  char curdir[8192];
  const char *utf8_ls_curdir, *utf8_is_curdir, *unencoded_url;

  if (! getcwd(curdir, sizeof(curdir)))
    return svn_error_create(SVN_ERR_BASE, NULL, "getcwd() failed");

  SVN_ERR(svn_utf_cstring_to_utf8(&utf8_ls_curdir, curdir, pool));
  utf8_is_curdir = svn_path_internal_style(utf8_ls_curdir, pool);

  unencoded_url = apr_psprintf(pool, "file://%s%s%s%s",
                               (utf8_is_curdir[0] != '/') ? "/" : "",
                               utf8_is_curdir,
                               (suffix[0] && suffix[0] != '/') ? "/" : "",
                               suffix);

  *url = svn_path_uri_encode(unencoded_url, pool);

  return SVN_NO_ERROR;
}
svn_error_t *
svn_error_wrap_apr(apr_status_t status,
                   const char *fmt,
                   ...)
{
  svn_error_t *err, *utf8_err;
  va_list ap;
  char errbuf[255];
  const char *msg_apr, *msg;

  err = make_error_internal(status, NULL);

  if (fmt)
    {
      /* Grab the APR error message. */
      apr_strerror(status, errbuf, sizeof(errbuf));
      utf8_err = svn_utf_cstring_to_utf8(&msg_apr, errbuf, err->pool);
      if (utf8_err)
        msg_apr = NULL;
      svn_error_clear(utf8_err);

      /* Append it to the formatted message. */
      va_start(ap, fmt);
      msg = apr_pvsprintf(err->pool, fmt, ap);
      va_end(ap);
      err->message = apr_psprintf(err->pool, "%s%s%s", msg,
                                  (msg_apr) ? ": " : "",
                                  (msg_apr) ? msg_apr : "");
    }

  return err;
}
Example #7
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__propdel(apr_getopt_t *os,
                void *baton,
                apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  const char *pname;
  apr_array_header_t *args, *targets;

  /* Get the property's name (and a UTF-8 version of that name). */
  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
  pname = APR_ARRAY_IDX(args, 0, const char *);
  SVN_ERR(svn_utf_cstring_to_utf8(&pname, pname, pool));
  /* No need to check svn_prop_name_is_valid for *deleting*
     properties, and it may even be useful to allow, in case invalid
     properties sneaked through somehow. */

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE, pool));


  /* Add "." if user passed 0 file arguments */
  svn_opt_push_implicit_dot_target(targets, pool);
  SVN_ERR(svn_cl__eat_peg_revisions(&targets, targets, pool));

  if (opt_state->revprop)  /* operate on a revprop */
    {
      svn_revnum_t rev;
      const char *URL;

      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
                                      &URL, ctx, pool));

      /* Let libsvn_client do the real work. */
      SVN_ERR(svn_client_revprop_set2(pname, NULL, NULL,
                                      URL, &(opt_state->start_revision),
                                      &rev, FALSE, ctx, pool));
    }
  else if (opt_state->start_revision.kind != svn_opt_revision_unspecified)
    {
      return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
               _("Cannot specify revision for deleting versioned property '%s'"),
               pname);
    }
  else  /* operate on a normal, versioned property (not a revprop) */
    {
      if (opt_state->depth == svn_depth_unknown)
        opt_state->depth = svn_depth_empty;

      /* For each target, remove the property PNAME. */
      SVN_ERR(svn_client_propset_local(pname, NULL, targets,
                                       opt_state->depth, FALSE,
                                       opt_state->changelists, ctx, pool));
    }

  return SVN_NO_ERROR;
}
Example #8
0
File: luasvn.c Project: ifzz/luasvn
static int
l_propget (lua_State *L) {
	apr_pool_t *pool;
	svn_error_t *err;
	svn_client_ctx_t *ctx;

	apr_hash_t *props;
	const char *propname_utf8;
	const void *key;
	void *val;
	apr_hash_index_t *hi;
	svn_opt_revision_t peg_revision;
	svn_opt_revision_t revision;

	const char *path = luaL_checkstring (L, 1);
	const char *propname = luaL_checkstring (L, 2);
	int itable = 4;
	svn_boolean_t recursive = FALSE;
	peg_revision.kind = svn_opt_revision_unspecified;

	if (lua_gettop (L) < 3 || lua_isnil (L, 3)) {
		revision.kind = svn_opt_revision_unspecified;
	} else {
		revision.kind = svn_opt_revision_number;
		revision.value.number = lua_tointeger (L, 3);
	}

	if (lua_gettop (L) >= itable && lua_istable (L, itable)) {
		lua_getfield (L, itable, "recursive");
		if (lua_isboolean (L, -1)) {
			recursive = lua_toboolean (L, -1);
		}
	} 

	init_function (&ctx, &pool, L);

	path = svn_path_canonicalize (path, pool);
	
	err = svn_utf_cstring_to_utf8 (&propname_utf8, propname, pool);
	IF_ERROR_RETURN (err, pool, L);

	err = svn_client_propget2 (&props, propname_utf8, path, &peg_revision, &revision, recursive, ctx, pool);
	IF_ERROR_RETURN (err, pool, L);

	lua_newtable (L);

	for (hi = apr_hash_first (pool, props); hi; hi = apr_hash_next (hi)) {
	  svn_string_t *s;
	  apr_hash_this (hi, &key, NULL, &val);
	  s = (svn_string_t *) val;
	  
	  lua_pushstring (L, s->data);
	  lua_setfield (L, -2, (char *) key);
	}

	svn_pool_destroy (pool);

	return 1;
}
Example #9
0
File: luasvn.c Project: ifzz/luasvn
static int
l_revprop_set (lua_State *L) {
	apr_pool_t *pool;
	svn_error_t *err;
	svn_client_ctx_t *ctx;

	svn_opt_revision_t revision;
   	svn_revnum_t rev;	
	
	const char *url = luaL_checkstring (L, 1);
	const char *propname = luaL_checkstring (L, 2);
	const char *propval = lua_isnil (L, 3) ? NULL : luaL_checkstring (L, 3);
	const char *propname_utf8 = NULL;
	int itable = 5;
	svn_boolean_t force = FALSE;

	if (lua_gettop (L) < 4 || lua_isnil (L, 4)) {
		revision.kind = get_revision_kind (url);
	} else {
		revision.kind = svn_opt_revision_number;
		revision.value.number = lua_tointeger (L, 4);
	}

	if (lua_gettop (L) >= itable && lua_istable (L, itable)) {
		lua_getfield (L, itable, "force");
		if (lua_isboolean (L, -1)) {
			force = lua_toboolean (L, -1);
		}
	} 

	init_function (&ctx, &pool, L);

	url = svn_path_canonicalize (url, pool);

	err = svn_utf_cstring_to_utf8 (&propname_utf8, propname, pool);
	IF_ERROR_RETURN (err, pool, L);

	if (propval != NULL) {
		svn_string_t *sstring = svn_string_create (propval, pool);

		if (svn_prop_needs_translation (propname_utf8)) {
			err = svn_subst_translate_string (&sstring, sstring, APR_LOCALE_CHARSET, pool);
			IF_ERROR_RETURN (err, pool, L);
		}
	
		err = svn_client_revprop_set (propname_utf8, sstring, url, &revision, &rev, force, ctx, pool);
	} else {
		err = svn_client_revprop_set (propname_utf8, NULL, url, &revision, &rev, force, ctx, pool);
	}
	IF_ERROR_RETURN (err, pool, L);
	
	svn_pool_destroy (pool);

	return 0;
}
Example #10
0
static int
l_propset (lua_State *L) {

	const char *path = luaL_checkstring (L, 1);
	const char *propname = luaL_checkstring (L, 2);
	const char *propval = lua_isnil (L, 3) ? NULL : luaL_checkstring (L, 3);

	
	svn_boolean_t recursive = FALSE;
	svn_boolean_t force = FALSE;
	
	int itable = 4;
	if (lua_gettop (L) >= itable && lua_istable (L, itable)) {
		
		lua_getfield (L, itable, "recursive");
		if (lua_isboolean (L, -1)) {
			recursive = lua_toboolean (L, -1);
		}
		
		lua_getfield (L, itable, "force");
		if (lua_isboolean (L, -1)) {
			force = lua_toboolean (L, -1);
		}
	} 


	apr_pool_t *pool;
	svn_error_t *err;
	svn_client_ctx_t *ctx;

	init_function (&ctx, &pool, L);

	path = svn_path_canonicalize (path, pool);

	const char *propname_utf8;
	err = svn_utf_cstring_to_utf8 (&propname_utf8, propname, pool);
	IF_ERROR_RETURN (err, pool, L);

	if (propval != NULL) {
		svn_string_t *sstring = svn_string_create (propval, pool);

		err = svn_client_propset2 (propname_utf8, sstring, path, recursive, force, ctx, pool);
	} else {
		err = svn_client_propset2 (propname_utf8, NULL, path, recursive, force, ctx, pool);
	}
	IF_ERROR_RETURN (err, pool, L);
	
	svn_pool_destroy (pool);

	return 0;

}
Example #11
0
svn_error_t *
svn_opt_parse_revprop(apr_hash_t **revprop_table_p, const char *revprop_spec,
                      apr_pool_t *pool)
{
  const char *sep, *propname;
  svn_string_t *propval;

  if (! *revprop_spec)
    return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                            _("Revision property pair is empty"));

  if (! *revprop_table_p)
    *revprop_table_p = apr_hash_make(pool);

  sep = strchr(revprop_spec, '=');
  if (sep)
    {
      propname = apr_pstrndup(pool, revprop_spec, sep - revprop_spec);
      SVN_ERR(svn_utf_cstring_to_utf8(&propname, propname, pool));
      propval = svn_string_create(sep + 1, pool);
    }
  else
    {
      SVN_ERR(svn_utf_cstring_to_utf8(&propname, revprop_spec, pool));
      propval = svn_string_create_empty(pool);
    }

  if (!svn_prop_name_is_valid(propname))
    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                             _("'%s' is not a valid Subversion property name"),
                             propname);

  svn_hash_sets(*revprop_table_p, propname, propval);

  return SVN_NO_ERROR;
}
Example #12
0
static svn_error_t *
log_msg_func2 (const char **log_msg,
		       const char **tmp_file,
			   const apr_array_header_t *commit_items,
			   void *baton,
			   apr_pool_t *pool)
{
	struct log_msg_baton *lmb = baton;

	svn_error_t *err = svn_utf_cstring_to_utf8 (log_msg, lmb->message, pool);
	IF_ERROR_RETURN (err, pool, lmb->L);

	*tmp_file = NULL;

	return SVN_NO_ERROR;
}
Example #13
0
static int
l_revprop_get (lua_State *L) {

	const char *url = luaL_checkstring (L, 1);
	const char *propname = luaL_checkstring (L, 2);

	svn_opt_revision_t revision;

	if (lua_gettop (L) < 3 || lua_isnil (L, 3)) {
		revision.kind = get_revision_kind (url);
	} else {
		revision.kind = svn_opt_revision_number;
		revision.value.number = lua_tointeger (L, 3);
	}

	apr_pool_t *pool;
	svn_error_t *err;
	svn_client_ctx_t *ctx;

	init_function (&ctx, &pool, L);

	url = svn_path_canonicalize (url, pool);

	const char *propname_utf8;
	err = svn_utf_cstring_to_utf8 (&propname_utf8, propname, pool);
	IF_ERROR_RETURN (err, pool, L);

	svn_string_t *propval;
	svn_revnum_t rev;

	err = svn_client_revprop_get (propname_utf8, &propval, url, &revision, &rev, ctx, pool);
	IF_ERROR_RETURN (err, pool, L);

	svn_string_t *printable_val = propval;
	if (svn_prop_needs_translation (propname_utf8)) {
		err = svn_subst_detranslate_string (&printable_val, propval, TRUE, pool);
		IF_ERROR_RETURN (err, pool, L);
	}

	lua_pushstring (L, printable_val->data);

	svn_pool_destroy (pool);

	return 1;

}
Example #14
0
/* Parse *PROP_NAME from HEADER as the part after the INDICATOR line.
 * Allocate *PROP_NAME in RESULT_POOL.
 * Set *PROP_NAME to NULL if no valid property name was found. */
static svn_error_t *
parse_prop_name(const char **prop_name, const char *header,
                const char *indicator, apr_pool_t *result_pool)
{
  SVN_ERR(svn_utf_cstring_to_utf8(prop_name,
                                  header + strlen(indicator),
                                  result_pool));
  if (**prop_name == '\0')
    *prop_name = NULL;
  else if (! svn_prop_name_is_valid(*prop_name))
    {
      svn_stringbuf_t *buf = svn_stringbuf_create(*prop_name, result_pool);
      svn_stringbuf_strip_whitespace(buf);
      *prop_name = (svn_prop_name_is_valid(buf->data) ? buf->data : NULL);
    }

  return SVN_NO_ERROR;
}
Example #15
0
/**
 * Build the error message from the svn error into buffer.  This
 * method calls itselft recursively for all the chained errors
 *
 * @param err               the subversion error
 * @param depth             the depth of the call, used for formating
 * @param parent_apr_err    the apr of the previous level, used for formating
 * @param buffer            the buffer where the formated error message will
 *                          be stored
 */
void JNIUtil::assembleErrorMessage(svn_error_t *err, int depth,
                                   apr_status_t parent_apr_err,
                                   std::string &buffer)
{
  // buffer for a single error message
  char errbuf[256];

  /* Pretty-print the error */
  /* Note: we can also log errors here someday. */

  /* When we're recursing, don't repeat the top-level message if its
   * the same as before. */
  if (depth == 0 || err->apr_err != parent_apr_err)
    {
      /* Is this a Subversion-specific error code? */
      if ((err->apr_err > APR_OS_START_USEERR)
          && (err->apr_err <= APR_OS_START_CANONERR))
        buffer.append(svn_strerror(err->apr_err, errbuf, sizeof(errbuf)));
      /* Otherwise, this must be an APR error code. */
      else
        {
          /* Messages coming from apr_strerror are in the native
             encoding, it's a good idea to convert them to UTF-8. */
          const char* utf8_message;
          apr_strerror(err->apr_err, errbuf, sizeof(errbuf));
          svn_error_t* utf8_err = svn_utf_cstring_to_utf8(
              &utf8_message, errbuf, err->pool);
          if (utf8_err)
            {
              /* Use fuzzy transliteration instead. */
              svn_error_clear(utf8_err);
              utf8_message = svn_utf_cstring_from_utf8_fuzzy(errbuf, err->pool);
            }
          buffer.append(utf8_message);
        }
      buffer.append("\n");
    }
  if (err->message)
    buffer.append(_("svn: ")).append(err->message).append("\n");

  if (err->child)
    assembleErrorMessage(err->child, depth + 1, err->apr_err, buffer);

}
int
main(int argc, const char **argv)
{
  apr_pool_t *pool;
  svn_error_t *err = SVN_NO_ERROR;
  const char *repos_path;

  /* Initialize the app.  Send all error messages to 'stderr'.  */
  if (svn_cmdline_init(argv[0], stderr) == EXIT_FAILURE)
    return EXIT_FAILURE;

  pool = svn_pool_create(NULL);

  if (argc <= 1)
    {
      usage_maybe_with_err(argv[0], "Not enough arguments.");
      goto cleanup;
    }

  /* Convert argv[1] into a UTF8, internal-format, canonicalized path. */
  if ((err = svn_utf_cstring_to_utf8(&repos_path, argv[1], pool)))
    goto cleanup;
  repos_path = svn_dirent_internal_style(repos_path, pool);
  repos_path = svn_dirent_canonicalize(repos_path, pool);

  if ((err = build_index(repos_path, pool)))
    goto cleanup;

 cleanup:
  svn_pool_destroy(pool);

  if (err)
    {
      svn_handle_error2(err, stderr, FALSE,
                        "svn-populate-node-origins-index: ");
      return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}
Example #17
0
CString SVNPatch::GetErrorMessageForNode(svn_error_t* Err) const
{
    CString msg;
    if (Err != NULL)
    {
        svn_error_t * ErrPtr = Err;
        if (ErrPtr->message)
            msg = CUnicodeUtils::GetUnicode(ErrPtr->message);
        else
        {
            char errbuf[256] = {0};
            /* Is this a Subversion-specific error code? */
            if ((ErrPtr->apr_err > APR_OS_START_USEERR)
                && (ErrPtr->apr_err <= APR_OS_START_CANONERR))
            {
                msg = svn_strerror (ErrPtr->apr_err, errbuf, _countof (errbuf));
            }
            /* Otherwise, this must be an APR error code. */
            else
            {
                svn_error_t *temp_err = NULL;
                const char * err_string = NULL;
                temp_err = svn_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, _countof (errbuf)-1), ErrPtr->pool);
                if (temp_err)
                {
                    svn_error_clear (temp_err);
                    msg = _T("Can't recode error string from APR");
                }
                else
                {
                    msg = CUnicodeUtils::GetUnicode(err_string);
                }
            }
        }
        msg = CStringUtils::LinesWrap(msg, 80);
    }
    return msg;
}
Example #18
0
/* UTF-8 encode and canonicalize the content of LINE as FILE_NAME. */
static svn_error_t *
grab_filename(const char **file_name, const char *line, apr_pool_t *result_pool,
              apr_pool_t *scratch_pool)
{
  const char *utf8_path;
  const char *canon_path;

  /* Grab the filename and encode it in UTF-8. */
  /* TODO: Allow specifying the patch file's encoding.
   *       For now, we assume its encoding is native. */
  /* ### This can fail if the filename cannot be represented in the current
   * ### locale's encoding. */
  SVN_ERR(svn_utf_cstring_to_utf8(&utf8_path,
                                  line,
                                  scratch_pool));

  /* Canonicalize the path name. */
  canon_path = svn_dirent_canonicalize(utf8_path, scratch_pool);

  *file_name = apr_pstrdup(result_pool, canon_path);

  return SVN_NO_ERROR;
}
Example #19
0
/* This implements the `svn_opt_subcommand_t' interface. */
svn_error_t *
svn_cl__propget(apr_getopt_t *os,
                void *baton,
                apr_pool_t *pool)
{
  svn_cl__opt_state_t *opt_state = ((svn_cl__cmd_baton_t *) baton)->opt_state;
  svn_client_ctx_t *ctx = ((svn_cl__cmd_baton_t *) baton)->ctx;
  const char *pname, *pname_utf8;
  apr_array_header_t *args, *targets;
  svn_stream_t *out;

  if (opt_state->verbose && (opt_state->revprop || opt_state->strict
                             || opt_state->xml))
    return svn_error_create(SVN_ERR_CL_MUTUALLY_EXCLUSIVE_ARGS, NULL,
                            _("--verbose cannot be used with --revprop or "
                              "--strict or --xml"));

  /* PNAME is first argument (and PNAME_UTF8 will be a UTF-8 version
     thereof) */
  SVN_ERR(svn_opt_parse_num_args(&args, os, 1, pool));
  pname = APR_ARRAY_IDX(args, 0, const char *);
  SVN_ERR(svn_utf_cstring_to_utf8(&pname_utf8, pname, pool));
  if (! svn_prop_name_is_valid(pname_utf8))
    return svn_error_createf(SVN_ERR_CLIENT_PROPERTY_NAME, NULL,
                             _("'%s' is not a valid Subversion property name"),
                             pname_utf8);

  SVN_ERR(svn_cl__args_to_target_array_print_reserved(&targets, os,
                                                      opt_state->targets,
                                                      ctx, FALSE, pool));

  /* Add "." if user passed 0 file arguments */
  svn_opt_push_implicit_dot_target(targets, pool);

  /* Open a stream to stdout. */
  SVN_ERR(svn_stream_for_stdout(&out, pool));

  if (opt_state->revprop)  /* operate on a revprop */
    {
      svn_revnum_t rev;
      const char *URL;
      svn_string_t *propval;

      SVN_ERR(svn_cl__revprop_prepare(&opt_state->start_revision, targets,
                                      &URL, ctx, pool));

      /* Let libsvn_client do the real work. */
      SVN_ERR(svn_client_revprop_get(pname_utf8, &propval,
                                     URL, &(opt_state->start_revision),
                                     &rev, ctx, pool));

      if (propval != NULL)
        {
          if (opt_state->xml)
            {
              svn_stringbuf_t *sb = NULL;
              char *revstr = apr_psprintf(pool, "%ld", rev);

              SVN_ERR(svn_cl__xml_print_header("properties", pool));

              svn_xml_make_open_tag(&sb, pool, svn_xml_normal,
                                    "revprops",
                                    "rev", revstr, NULL);

              svn_cmdline__print_xml_prop(&sb, pname_utf8, propval, pool);

              svn_xml_make_close_tag(&sb, pool, "revprops");

              SVN_ERR(svn_cl__error_checked_fputs(sb->data, stdout));
              SVN_ERR(svn_cl__xml_print_footer("properties", pool));
            }
          else
            {
              svn_string_t *printable_val = propval;

              /* If this is a special Subversion property, it is stored as
                 UTF8 and LF, so convert to the native locale and eol-style. */

              if (svn_prop_needs_translation(pname_utf8))
                SVN_ERR(svn_subst_detranslate_string(&printable_val, propval,
                                                     TRUE, pool));

              SVN_ERR(stream_write(out, printable_val->data,
                                   printable_val->len));
              if (! opt_state->strict)
                SVN_ERR(stream_write(out, APR_EOL_STR, strlen(APR_EOL_STR)));
            }
        }
    }
  else  /* operate on a normal, versioned property (not a revprop) */
    {
      apr_pool_t *subpool = svn_pool_create(pool);
      int i;

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_header("properties", subpool));

      if (opt_state->depth == svn_depth_unknown)
        opt_state->depth = svn_depth_empty;

      /* Strict mode only makes sense for a single target.  So make
         sure we have only a single target, and that we're not being
         asked to recurse on that target. */
      if (opt_state->strict
          && ((targets->nelts > 1) || (opt_state->depth != svn_depth_empty)))
        return svn_error_create
          (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
           _("Strict output of property values only available for single-"
             "target, non-recursive propget operations"));

      for (i = 0; i < targets->nelts; i++)
        {
          const char *target = APR_ARRAY_IDX(targets, i, const char *);
          apr_hash_t *props;
          svn_boolean_t print_filenames;
          svn_boolean_t omit_newline;
          svn_boolean_t like_proplist;
          const char *truepath;
          svn_opt_revision_t peg_revision;

          svn_pool_clear(subpool);
          SVN_ERR(svn_cl__check_cancel(ctx->cancel_baton));

          /* Check for a peg revision. */
          SVN_ERR(svn_opt_parse_path(&peg_revision, &truepath, target,
                                     subpool));

          if (!svn_path_is_url(truepath))
            SVN_ERR(svn_dirent_get_absolute(&truepath, truepath, subpool));

          SVN_ERR(svn_client_propget4(&props, pname_utf8, truepath,
                                      &peg_revision,
                                      &(opt_state->start_revision),
                                      NULL, opt_state->depth,
                                      opt_state->changelists, ctx, subpool,
                                      subpool));

          /* Any time there is more than one thing to print, or where
             the path associated with a printed thing is not obvious,
             we'll print filenames.  That is, unless we've been told
             not to do so with the --strict option. */
          print_filenames = ((opt_state->depth > svn_depth_empty
                              || targets->nelts > 1
                              || apr_hash_count(props) > 1
                              || opt_state->verbose)
                             && (! opt_state->strict));
          omit_newline = opt_state->strict;
          like_proplist = opt_state->verbose && !opt_state->strict;

          if (opt_state->xml)
            SVN_ERR(print_properties_xml(pname_utf8, props, subpool));
          else
            SVN_ERR(print_properties(out, svn_path_is_url(target), pname_utf8,
                                     props, print_filenames, omit_newline,
                                     like_proplist, subpool));
        }

      if (opt_state->xml)
        SVN_ERR(svn_cl__xml_print_footer("properties", subpool));

      svn_pool_destroy(subpool);
    }

  return SVN_NO_ERROR;
}
Example #20
0
/*
 * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
 * either return an error to be displayed, or set *EXIT_CODE to non-zero and
 * return SVN_NO_ERROR.
 */
static svn_error_t *
sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
  apr_getopt_t *os;
  const apr_getopt_option_t options[] =
    {
      {"help", 'h', 0, N_("display this help")},
      {"version", OPT_VERSION, 0,
       N_("show program version information")},
      {0,             0,  0,  0}
    };
  apr_array_header_t *remaining_argv;

  /* Check library versions */
  SVN_ERR(check_lib_versions());

#if defined(WIN32) || defined(__CYGWIN__)
  /* Set the working copy administrative directory name. */
  if (getenv("SVN_ASP_DOT_NET_HACK"))
    {
      SVN_ERR(svn_wc_set_adm_dir("_svn", pool));
    }
#endif

  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));

  os->interleave = 1;
  while (1)
    {
      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)
        {
          usage(pool);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }

      switch (opt)
        {
        case 'h':
          help(options, pool);
          return SVN_NO_ERROR;
        case OPT_VERSION:
          SVN_ERR(version(pool));
          return SVN_NO_ERROR;
        default:
          usage(pool);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }
    }

  /* Convert the remaining arguments to UTF-8. */
  remaining_argv = apr_array_make(pool, 0, sizeof(const char *));
  while (os->ind < argc)
    {
      const char *s;

      SVN_ERR(svn_utf_cstring_to_utf8(&s, os->argv[os->ind++], pool));
      APR_ARRAY_PUSH(remaining_argv, const char *) = s;
    }

  if (remaining_argv->nelts < 1)
    {
      usage(pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  /* Do the main task */
  SVN_ERR(raise_tree_conflict(remaining_argv->nelts,
                              (const char **)remaining_argv->elts,
                              pool));

  return SVN_NO_ERROR;
}
Example #21
0
CString CAppUtils::GetErrorString(svn_error_t * Err)
{
	CString msg;
	CString temp;
	char errbuf[256];

	if (Err != NULL)
	{
		svn_error_t * ErrPtr = Err;
		if (ErrPtr->message)
			msg = CUnicodeUtils::GetUnicode(ErrPtr->message);
		else
		{
			/* Is this a Subversion-specific error code? */
			if ((ErrPtr->apr_err > APR_OS_START_USEERR)
				&& (ErrPtr->apr_err <= APR_OS_START_CANONERR))
				msg = svn_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf));
			/* Otherwise, this must be an APR error code. */
			else
			{
				svn_error_t *temp_err = NULL;
				const char * err_string = NULL;
				temp_err = svn_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);
				if (temp_err)
				{
					svn_error_clear (temp_err);
					msg = _T("Can't recode error string from APR");
				}
				else
				{
					msg = CUnicodeUtils::GetUnicode(err_string);
				}
			}
		}
		while (ErrPtr->child)
		{
			ErrPtr = ErrPtr->child;
			msg += _T("\n");
			if (ErrPtr->message)
				temp = CUnicodeUtils::GetUnicode(ErrPtr->message);
			else
			{
				/* Is this a Subversion-specific error code? */
				if ((ErrPtr->apr_err > APR_OS_START_USEERR)
					&& (ErrPtr->apr_err <= APR_OS_START_CANONERR))
					temp = svn_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf));
				/* Otherwise, this must be an APR error code. */
				else
				{
					svn_error_t *temp_err = NULL;
					const char * err_string = NULL;
					temp_err = svn_utf_cstring_to_utf8(&err_string, apr_strerror (ErrPtr->apr_err, errbuf, sizeof (errbuf)-1), ErrPtr->pool);
					if (temp_err)
					{
						svn_error_clear (temp_err);
						temp = _T("Can't recode error string from APR");
					}
					else
					{
						temp = CUnicodeUtils::GetUnicode(err_string);
					}
				}
			}
			msg += temp;
		}
		return msg;
	}
	return _T("");
}
Example #22
0
/*
 * Why is this not an svn subcommand?  I have this vague idea that it could
 * be run as part of the build process, with the output embedded in the svn
 * program.  Obviously we don't want to have to run svn when building svn.
 */
int
main(int argc, const char *argv[])
{
  const char *wc_path, *trail_url;
  apr_allocator_t *allocator;
  apr_pool_t *pool;
  int wc_format;
  svn_wc_revision_status_t *res;
  svn_boolean_t no_newline = FALSE, committed = FALSE;
  svn_error_t *err;
  apr_getopt_t *os;
  const apr_getopt_option_t options[] =
    {
      {"no-newline", 'n', 0, N_("do not output the trailing newline")},
      {"committed",  'c', 0, N_("last changed rather than current revisions")},
      {"help", 'h', 0, N_("display this help")},
      {"version", SVNVERSION_OPT_VERSION, 0,
       N_("show program version information")},
      {0,             0,  0,  0}
    };

  /* Initialize the app. */
  if (svn_cmdline_init("svnversion", stderr) != EXIT_SUCCESS)
    return EXIT_FAILURE;

  /* Create our top-level pool.  Use a separate mutexless allocator,
   * given this application is single threaded.
   */
  if (apr_allocator_create(&allocator))
    return EXIT_FAILURE;

  apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);

  pool = svn_pool_create_ex(NULL, allocator);
  apr_allocator_owner_set(allocator, pool);

  /* Check library versions */
  err = check_lib_versions();
  if (err)
    return svn_cmdline_handle_exit_error(err, pool, "svnversion: ");

#if defined(WIN32) || defined(__CYGWIN__)
  /* Set the working copy administrative directory name. */
  if (getenv("SVN_ASP_DOT_NET_HACK"))
    {
      err = svn_wc_set_adm_dir("_svn", pool);
      if (err)
        return svn_cmdline_handle_exit_error(err, pool, "svnversion: ");
    }
#endif

  err = svn_cmdline__getopt_init(&os, argc, argv, pool);
  if (err)
    return svn_cmdline_handle_exit_error(err, pool, "svnversion: ");

  os->interleave = 1;
  while (1)
    {
      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)
        {
          usage(pool);
          return EXIT_FAILURE;
        }
      switch (opt)
        {
        case 'n':
          no_newline = TRUE;
          break;
        case 'c':
          committed = TRUE;
          break;
        case 'h':
          help(options, pool);
          break;
        case SVNVERSION_OPT_VERSION:
          SVN_INT_ERR(version(pool));
          exit(0);
          break;
        default:
          usage(pool);
          return EXIT_FAILURE;
        }
    }

  if (os->ind > argc || os->ind < argc - 2)
    {
      usage(pool);
      return EXIT_FAILURE;
    }

  SVN_INT_ERR(svn_utf_cstring_to_utf8
              (&wc_path, (os->ind < argc) ? os->argv[os->ind] : ".",
               pool));
  wc_path = svn_path_internal_style(wc_path, pool);

  if (os->ind+1 < argc)
    SVN_INT_ERR(svn_utf_cstring_to_utf8
                (&trail_url, os->argv[os->ind+1], pool));
  else
    trail_url = NULL;

  SVN_INT_ERR(svn_wc_check_wc(wc_path, &wc_format, pool));
  if (! wc_format)
    {
      svn_node_kind_t kind;
      SVN_INT_ERR(svn_io_check_path(wc_path, &kind, pool));
      if (kind == svn_node_dir)
        {
          SVN_INT_ERR(svn_cmdline_printf(pool, _("exported%s"),
                                         no_newline ? "" : "\n"));
          svn_pool_destroy(pool);
          return EXIT_SUCCESS;
        }
      else
        {
          svn_error_clear
            (svn_cmdline_fprintf(stderr, pool,
                                 _("'%s' not versioned, and not exported\n"),
                                 wc_path));
          svn_pool_destroy(pool);
          return EXIT_FAILURE;
        }
    }


  SVN_INT_ERR(svn_wc_revision_status(&res, wc_path, trail_url, committed,
                                     NULL, NULL, pool));

  /* Build compact '123[:456]M?S?' string. */
  SVN_INT_ERR(svn_cmdline_printf(pool, "%ld", res->min_rev));
  if (res->min_rev != res->max_rev)
    SVN_INT_ERR(svn_cmdline_printf(pool, ":%ld", res->max_rev));
  if (res->modified)
    SVN_INT_ERR(svn_cmdline_fputs("M", stdout, pool));
  if (res->switched)
    SVN_INT_ERR(svn_cmdline_fputs("S", stdout, pool));
  if (res->sparse_checkout)
    SVN_INT_ERR(svn_cmdline_fputs("P", stdout, pool));

  if (! no_newline)
    SVN_INT_ERR(svn_cmdline_fputs("\n", stdout, pool));

  svn_pool_destroy(pool);

  /* Flush stdout to make sure that the user will see any printing errors. */
  SVN_INT_ERR(svn_cmdline_fflush(stdout));

  return EXIT_SUCCESS;
}
Example #23
0
int
main(int argc, const char **argv)
{
    svn_error_t *err = SVN_NO_ERROR;
    const svn_opt_subcommand_desc2_t *subcommand = NULL;
    opt_baton_t *opt_baton;
    svn_revnum_t latest_revision = SVN_INVALID_REVNUM;
    apr_pool_t *pool = NULL;
    const char *config_dir = NULL;
    const char *username = NULL;
    const char *password = NULL;
    svn_boolean_t no_auth_cache = FALSE;
    svn_boolean_t trust_server_cert = FALSE;
    svn_boolean_t non_interactive = FALSE;
    apr_array_header_t *config_options = NULL;
    apr_getopt_t *os;
    const char *first_arg;
    apr_array_header_t *received_opts;
    apr_allocator_t *allocator;
    int i;

    if (svn_cmdline_init ("svnrdump", stderr) != EXIT_SUCCESS)
        return EXIT_FAILURE;

    /* Create our top-level pool.  Use a separate mutexless allocator,
     * given this application is single threaded.
     */
    if (apr_allocator_create(&allocator))
        return EXIT_FAILURE;

    apr_allocator_max_free_set(allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);

    pool = svn_pool_create_ex(NULL, allocator);
    apr_allocator_owner_set(allocator, pool);

    opt_baton = apr_pcalloc(pool, sizeof(*opt_baton));
    opt_baton->start_revision.kind = svn_opt_revision_unspecified;
    opt_baton->end_revision.kind = svn_opt_revision_unspecified;
    opt_baton->url = NULL;

    SVNRDUMP_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));

    os->interleave = TRUE; /* Options and arguments can be interleaved */

    /* Set up our cancellation support. */
    apr_signal(SIGINT, signal_handler);
#ifdef SIGBREAK
    /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */
    apr_signal(SIGBREAK, signal_handler);
#endif
#ifdef SIGHUP
    apr_signal(SIGHUP, signal_handler);
#endif
#ifdef SIGTERM
    apr_signal(SIGTERM, signal_handler);
#endif
#ifdef SIGPIPE
    /* Disable SIGPIPE generation for the platforms that have it. */
    apr_signal(SIGPIPE, SIG_IGN);
#endif
#ifdef SIGXFSZ
    /* Disable SIGXFSZ generation for the platforms that have it, otherwise
     * working with large files when compiled against an APR that doesn't have
     * large file support will crash the program, which is uncool. */
    apr_signal(SIGXFSZ, SIG_IGN);
#endif

    received_opts = apr_array_make(pool, SVN_OPT_MAX_OPTIONS, sizeof(int));

    while (1)
    {
        int opt;
        const char *opt_arg;
        apr_status_t status = apr_getopt_long(os, svnrdump__options, &opt,
                                              &opt_arg);

        if (APR_STATUS_IS_EOF(status))
            break;
        if (status != APR_SUCCESS)
        {
            SVNRDUMP_ERR(usage(argv[0], pool));
            exit(EXIT_FAILURE);
        }

        /* Stash the option code in an array before parsing it. */
        APR_ARRAY_PUSH(received_opts, int) = opt;

        switch(opt)
        {
        case 'r':
        {
            /* Make sure we've not seen -r already. */
            if (opt_baton->start_revision.kind != svn_opt_revision_unspecified)
            {
                err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                       _("Multiple revision arguments "
                                         "encountered; try '-r N:M' instead "
                                         "of '-r N -r M'"));
                return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
            }
            /* Parse the -r argument. */
            if (svn_opt_parse_revision(&(opt_baton->start_revision),
                                       &(opt_baton->end_revision),
                                       opt_arg, pool) != 0)
            {
                const char *utf8_opt_arg;
                err = svn_utf_cstring_to_utf8(&utf8_opt_arg, opt_arg, pool);
                if (! err)
                    err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                                            _("Syntax error in revision "
                                              "argument '%s'"), utf8_opt_arg);
                return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
            }
        }
        break;
        case 'q':
            opt_baton->quiet = TRUE;
            break;
        case opt_config_dir:
            config_dir = opt_arg;
            break;
        case opt_version:
            opt_baton->version = TRUE;
            break;
        case 'h':
            opt_baton->help = TRUE;
            break;
        case opt_auth_username:
            SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&username, opt_arg, pool));
            break;
        case opt_auth_password:
            SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&password, opt_arg, pool));
            break;
        case opt_auth_nocache:
            no_auth_cache = TRUE;
            break;
        case opt_non_interactive:
            non_interactive = TRUE;
            break;
        case opt_incremental:
            opt_baton->incremental = TRUE;
            break;
        case opt_trust_server_cert:
            trust_server_cert = TRUE;
            break;
        case opt_config_option:
            if (!config_options)
                config_options =
                    apr_array_make(pool, 1,
                                   sizeof(svn_cmdline__config_argument_t*));

            SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&opt_arg, opt_arg, pool));
            SVNRDUMP_ERR(svn_cmdline__parse_config_option(config_options,
                         opt_arg, pool));
        }
    }

    if (opt_baton->help)
    {
        subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table,
                     "help");
    }
    if (subcommand == NULL)
    {
        if (os->ind >= os->argc)
        {
            if (opt_baton->version)
            {
                /* Use the "help" subcommand to handle the "--version" option. */
                static const svn_opt_subcommand_desc2_t pseudo_cmd =
                {   "--version", help_cmd, {0}, "",
                    {   opt_version,  /* must accept its own option */
                        'q',  /* --quiet */
                    }
                };
                subcommand = &pseudo_cmd;
            }

            else
            {
                SVNRDUMP_ERR(help_cmd(NULL, NULL, pool));
                svn_pool_destroy(pool);
                exit(EXIT_FAILURE);
            }
        }
        else
        {
            first_arg = os->argv[os->ind++];
            subcommand = svn_opt_get_canonical_subcommand2(svnrdump__cmd_table,
                         first_arg);

            if (subcommand == NULL)
            {
                const char *first_arg_utf8;
                err = svn_utf_cstring_to_utf8(&first_arg_utf8, first_arg, pool);
                if (err)
                    return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
                svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                                                    _("Unknown command: '%s'\n"),
                                                    first_arg_utf8));
                SVNRDUMP_ERR(help_cmd(NULL, NULL, pool));
                svn_pool_destroy(pool);
                exit(EXIT_FAILURE);
            }
        }
    }

    /* Check that the subcommand wasn't passed any inappropriate options. */
    for (i = 0; i < received_opts->nelts; i++)
    {
        int opt_id = APR_ARRAY_IDX(received_opts, i, int);

        /* 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;

        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, svnrdump__options,
                                              subcommand, pool);
            svn_opt_format_option(&optstr, badopt, FALSE, pool);
            if (subcommand->name[0] == '-')
                SVN_INT_ERR(help_cmd(NULL, NULL, pool));
            else
                svn_error_clear(svn_cmdline_fprintf(
                                    stderr, pool,
                                    _("Subcommand '%s' doesn't accept option '%s'\n"
                                      "Type 'svnrdump help %s' for usage.\n"),
                                    subcommand->name, optstr, subcommand->name));
            svn_pool_destroy(pool);
            return EXIT_FAILURE;
        }
    }

    if (subcommand && strcmp(subcommand->name, "--version") == 0)
    {
        SVNRDUMP_ERR(version(argv[0], opt_baton->quiet, pool));
        svn_pool_destroy(pool);
        exit(EXIT_SUCCESS);
    }

    if (subcommand && strcmp(subcommand->name, "help") == 0)
    {
        SVNRDUMP_ERR(help_cmd(os, opt_baton, pool));
        svn_pool_destroy(pool);
        exit(EXIT_SUCCESS);
    }

    /* --trust-server-cert can only be used with --non-interactive */
    if (trust_server_cert && !non_interactive)
    {
        err = svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                               _("--trust-server-cert requires "
                                 "--non-interactive"));
        return svn_cmdline_handle_exit_error(err, pool, "svnrdump: ");
    }

    /* Expect one more non-option argument:  the repository URL. */
    if (os->ind != os->argc - 1)
    {
        SVNRDUMP_ERR(usage(argv[0], pool));
        svn_pool_destroy(pool);
        exit(EXIT_FAILURE);
    }
    else
    {
        const char *repos_url;

        SVNRDUMP_ERR(svn_utf_cstring_to_utf8(&repos_url,
                                             os->argv[os->ind], pool));
        if (! svn_path_is_url(repos_url))
        {
            err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, 0,
                                    "Target '%s' is not a URL",
                                    repos_url);
            SVNRDUMP_ERR(err);
            svn_pool_destroy(pool);
            exit(EXIT_FAILURE);
        }
        opt_baton->url = svn_uri_canonicalize(repos_url, pool);
    }

    SVNRDUMP_ERR(init_client_context(&(opt_baton->ctx),
                                     non_interactive,
                                     username,
                                     password,
                                     config_dir,
                                     no_auth_cache,
                                     trust_server_cert,
                                     config_options,
                                     pool));

    SVNRDUMP_ERR(svn_client_open_ra_session(&(opt_baton->session),
                                            opt_baton->url,
                                            opt_baton->ctx, pool));

    /* Have sane opt_baton->start_revision and end_revision defaults if
       unspecified.  */
    SVNRDUMP_ERR(svn_ra_get_latest_revnum(opt_baton->session,
                                          &latest_revision, pool));

    /* Make sure any provided revisions make sense. */
    SVNRDUMP_ERR(validate_and_resolve_revisions(opt_baton,
                 latest_revision, pool));

    /* Dispatch the subcommand */
    SVNRDUMP_ERR((*subcommand->cmd_func)(os, opt_baton, pool));

    svn_pool_destroy(pool);

    return EXIT_SUCCESS;
}
Example #24
0
const char *
svn_time_to_human_cstring(apr_time_t when, apr_pool_t *pool)
{
    apr_time_exp_t exploded_time;
    apr_size_t len, retlen;
    apr_status_t ret;
    char *datestr, *curptr, human_datestr[SVN_TIME__MAX_LENGTH];

    /* Get the time into parts */
    ret = apr_time_exp_lt(&exploded_time, when);
    if (ret)
        return NULL;

    /* Make room for datestring */
    datestr = apr_palloc(pool, SVN_TIME__MAX_LENGTH);

    /* Put in machine parseable part */
    len = apr_snprintf(datestr,
                       SVN_TIME__MAX_LENGTH,
                       HUMAN_TIMESTAMP_FORMAT,
                       exploded_time.tm_year + 1900,
                       exploded_time.tm_mon + 1,
                       exploded_time.tm_mday,
                       exploded_time.tm_hour,
                       exploded_time.tm_min,
                       exploded_time.tm_sec,
                       exploded_time.tm_gmtoff / (60 * 60),
                       (abs(exploded_time.tm_gmtoff) / 60) % 60);

    /* If we overfilled the buffer, just return what we got. */
    if (len >= SVN_TIME__MAX_LENGTH)
        return datestr;

    /* Calculate offset to the end of the machine parseable part. */
    curptr = datestr + len;

    /* Put in human explanatory part */
    ret = apr_strftime(human_datestr,
                       &retlen,
                       SVN_TIME__MAX_LENGTH - len,
                       human_timestamp_format_suffix,
                       &exploded_time);

    /* If there was an error, ensure that the string is zero-terminated. */
    if (ret || retlen == 0)
        *curptr = '\0';
    else
    {
        const char *utf8_string;
        svn_error_t *err;

        err = svn_utf_cstring_to_utf8(&utf8_string, human_datestr, pool);
        if (err)
        {
            *curptr = '\0';
            svn_error_clear(err);
        }
        else
            apr_cpystrn(curptr, utf8_string, SVN_TIME__MAX_LENGTH - len);
    }

    return datestr;
}
Example #25
0
/* Opens a session */
char session_open(session_t *session)
{
	svn_error_t *err;
	svn_client_ctx_t *ctx;
	svn_config_t *config;
	svn_auth_baton_t *auth_baton;
	const char *root;
	const char *config_dir = NULL;

	/* Make sure the URL is properly encoded */
	session->encoded_url = svn_path_uri_encode(svn_path_canonicalize(session->url, session->pool), session->pool);

	/* Do neccessary SVN library initialization */
	if ((err = svn_fs_initialize(session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}
	if ((err = svn_ra_initialize(session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}

	if ((err = svn_config_ensure(NULL, session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}

	/* Setup the client context */
	if ((err = svn_client_create_context(&ctx, session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}

	if ((err = svn_config_get_config(&(ctx->config), NULL, session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}

	if (session->config_dir != NULL) {
		const char *path;
		if ((err = svn_utf_cstring_to_utf8(&path, session->config_dir, session->pool))) {
			utils_handle_error(err, stderr, FALSE, "ERROR: ");
			svn_error_clear(err);
			return 1;
		}
		config_dir = svn_path_canonicalize(path, session->pool);
	}

	/* Setup auth baton */
	config = apr_hash_get(ctx->config, SVN_CONFIG_CATEGORY_CONFIG, APR_HASH_KEY_STRING);
	if ((err = svn_cmdline_setup_auth_baton(&auth_baton, (session->flags & SF_NON_INTERACTIVE), session->username, session->password, config_dir, (session->flags & SF_NO_AUTH_CACHE), config, NULL, NULL, session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}
	ctx->auth_baton = auth_baton;

	/* Setup the RA session */
	if ((err = svn_client_open_ra_session(&(session->ra), session->encoded_url, ctx, session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}

	/* Determine the root (and the prefix) of the URL */
	if ((err = svn_ra_get_repos_root(session->ra, &root, session->pool))) {
		utils_handle_error(err, stderr, FALSE, "ERROR: ");
		svn_error_clear(err);
		return 1;
	}
	session->root = root;
	if (!strcmp(session->encoded_url, root)) {
		session->prefix = apr_pstrdup(session->pool, "");
	} else {
		session->prefix = apr_pstrdup(session->pool, session->encoded_url + strlen(root) + 1);
	}
	session->prefix = session_obfuscate(session, session->pool, session->prefix);

	return 0;
}
Example #26
0
/* Note: This is substantially copied into svn_client_args_to_target_array() in
 * order to move to libsvn_client while maintaining backward compatibility. */
svn_error_t *
svn_opt__args_to_target_array(apr_array_header_t **targets_p,
                              apr_getopt_t *os,
                              const apr_array_header_t *known_targets,
                              apr_pool_t *pool)
{
  int i;
  svn_error_t *err = SVN_NO_ERROR;
  apr_array_header_t *input_targets =
    apr_array_make(pool, DEFAULT_ARRAY_SIZE, sizeof(const char *));
  apr_array_header_t *output_targets =
    apr_array_make(pool, DEFAULT_ARRAY_SIZE, sizeof(const char *));

  /* Step 1:  create a master array of targets that are in UTF-8
     encoding, and come from concatenating the targets left by apr_getopt,
     plus any extra targets (e.g., from the --targets switch.) */

  for (; os->ind < os->argc; os->ind++)
    {
      /* The apr_getopt targets are still in native encoding. */
      const char *raw_target = os->argv[os->ind];
      SVN_ERR(svn_utf_cstring_to_utf8
              ((const char **) apr_array_push(input_targets),
               raw_target, pool));
    }

  if (known_targets)
    {
      for (i = 0; i < known_targets->nelts; i++)
        {
          /* The --targets array have already been converted to UTF-8,
             because we needed to split up the list with svn_cstring_split. */
          const char *utf8_target = APR_ARRAY_IDX(known_targets,
                                                  i, const char *);
          APR_ARRAY_PUSH(input_targets, const char *) = utf8_target;
        }
    }

  /* Step 2:  process each target.  */

  for (i = 0; i < input_targets->nelts; i++)
    {
      const char *utf8_target = APR_ARRAY_IDX(input_targets, i, const char *);
      const char *true_target;
      const char *target;      /* after all processing is finished */
      const char *peg_rev;

      /*
       * This is needed so that the target can be properly canonicalized,
       * otherwise the canonicalization does not treat a ".@BASE" as a "."
       * with a BASE peg revision, and it is not canonicalized to "@BASE".
       * If any peg revision exists, it is appended to the final
       * canonicalized path or URL.  Do not use svn_opt_parse_path()
       * because the resulting peg revision is a structure that would have
       * to be converted back into a string.  Converting from a string date
       * to the apr_time_t field in the svn_opt_revision_value_t and back to
       * a string would not necessarily preserve the exact bytes of the
       * input date, so its easier just to keep it in string form.
       */
      SVN_ERR(svn_opt__split_arg_at_peg_revision(&true_target, &peg_rev,
                                                 utf8_target, pool));

      /* URLs and wc-paths get treated differently. */
      if (svn_path_is_url(true_target))
        {
          SVN_ERR(svn_opt__arg_canonicalize_url(&true_target, true_target,
                                                 pool));
        }
      else  /* not a url, so treat as a path */
        {
          const char *base_name;

          SVN_ERR(svn_opt__arg_canonicalize_path(&true_target, true_target,
                                                 pool));

          /* If the target has the same name as a Subversion
             working copy administrative dir, skip it. */
          base_name = svn_dirent_basename(true_target, pool);

          /* FIXME:
             The canonical list of administrative directory names is
             maintained in libsvn_wc/adm_files.c:svn_wc_set_adm_dir().
             That list can't be used here, because that use would
             create a circular dependency between libsvn_wc and
             libsvn_subr.  Make sure changes to the lists are always
             synchronized! */
          if (0 == strcmp(base_name, ".svn")
              || 0 == strcmp(base_name, "_svn"))
            {
              err = svn_error_createf(SVN_ERR_RESERVED_FILENAME_SPECIFIED,
                                      err, _("'%s' ends in a reserved name"),
                                      utf8_target);
              continue;
            }
        }

      target = apr_pstrcat(pool, true_target, peg_rev, (char *)NULL);

      APR_ARRAY_PUSH(output_targets, const char *) = target;
    }


  /* kff todo: need to remove redundancies from targets before
     passing it to the cmd_func. */

  *targets_p = output_targets;

  return err;
}
Example #27
0
/* Helper function for run_hook_cmd().  Wait for a hook to finish
   executing and return either SVN_NO_ERROR if the hook script completed
   without error, or an error describing the reason for failure.

   NAME and CMD are the name and path of the hook program, CMD_PROC
   is a pointer to the structure representing the running process,
   and READ_ERRHANDLE is an open handle to the hook's stderr.

   Hooks are considered to have failed if we are unable to wait for the
   process, if we are unable to read from the hook's stderr, if the
   process has failed to exit cleanly (due to a coredump, for example),
   or if the process returned a non-zero return code.

   Any error output returned by the hook's stderr will be included in an
   error message, though the presence of output on stderr is not itself
   a reason to fail a hook. */
static svn_error_t *
check_hook_result(const char *name, const char *cmd, apr_proc_t *cmd_proc,
                  apr_file_t *read_errhandle, apr_pool_t *pool)
{
  svn_error_t *err, *err2;
  svn_stringbuf_t *native_stderr, *failure_message;
  const char *utf8_stderr;
  int exitcode;
  apr_exit_why_e exitwhy;

  err2 = svn_stringbuf_from_aprfile(&native_stderr, read_errhandle, pool);

  err = svn_io_wait_for_cmd(cmd_proc, cmd, &exitcode, &exitwhy, pool);
  if (err)
    {
      svn_error_clear(err2);
      return svn_error_trace(err);
    }

  if (APR_PROC_CHECK_EXIT(exitwhy) && exitcode == 0)
    {
      /* The hook exited cleanly.  However, if we got an error reading
         the hook's stderr, fail the hook anyway, because this might be
         symptomatic of a more important problem. */
      if (err2)
        {
          return svn_error_createf
            (SVN_ERR_REPOS_HOOK_FAILURE, err2,
             _("'%s' hook succeeded, but error output could not be read"),
             name);
        }

      return SVN_NO_ERROR;
    }

  /* The hook script failed. */

  /* If we got the stderr output okay, try to translate it into UTF-8.
     Ensure there is something sensible in the UTF-8 string regardless. */
  if (!err2)
    {
      err2 = svn_utf_cstring_to_utf8(&utf8_stderr, native_stderr->data, pool);
      if (err2)
        utf8_stderr = _("[Error output could not be translated from the "
                        "native locale to UTF-8.]");
    }
  else
    {
      utf8_stderr = _("[Error output could not be read.]");
    }
  /*### It would be nice to include the text of any translation or read
        error in the messages above before we clear it here. */
  svn_error_clear(err2);

  if (!APR_PROC_CHECK_EXIT(exitwhy))
    {
      failure_message = svn_stringbuf_createf(pool,
        _("'%s' hook failed (did not exit cleanly: "
          "apr_exit_why_e was %d, exitcode was %d).  "),
        name, exitwhy, exitcode);
    }
  else
    {
      const char *action;
      if (strcmp(name, "start-commit") == 0
          || strcmp(name, "pre-commit") == 0)
        action = _("Commit");
      else if (strcmp(name, "pre-revprop-change") == 0)
        action = _("Revprop change");
      else if (strcmp(name, "pre-lock") == 0)
        action = _("Lock");
      else if (strcmp(name, "pre-unlock") == 0)
        action = _("Unlock");
      else
        action = NULL;
      if (action == NULL)
        failure_message = svn_stringbuf_createf(
            pool, _("%s hook failed (exit code %d)"),
            name, exitcode);
      else
        failure_message = svn_stringbuf_createf(
            pool, _("%s blocked by %s hook (exit code %d)"),
            action, name, exitcode);
    }

  if (utf8_stderr[0])
    {
      svn_stringbuf_appendcstr(failure_message,
                               _(" with output:\n"));
      svn_stringbuf_appendcstr(failure_message, utf8_stderr);
    }
  else
    {
      svn_stringbuf_appendcstr(failure_message,
                               _(" with no output."));
    }

  return svn_error_create(SVN_ERR_REPOS_HOOK_FAILURE, err,
                          failure_message->data);
}
Example #28
0
File: main.c Project: ejrh/ejrh
int
main (int argc, const char * const *argv)
{
  svn_error_t *err;
  apr_status_t apr_err;
  apr_allocator_t *allocator;
  apr_pool_t *pool;

  const svn_opt_subcommand_desc_t *subcommand = NULL;
  struct svnindex_opt_state opt_state;
  apr_getopt_t *os;  
  int opt_id;
  apr_array_header_t *received_opts;
  int i;

  /* Initialize the app. */
  if (svn_cmdline_init ("svnindex", stderr) != EXIT_SUCCESS)
    return EXIT_FAILURE;

  /* Create our top-level pool.  Use a seperate mutexless allocator,
   * given this application is single threaded.
   */
  if (apr_allocator_create (&allocator))
    return EXIT_FAILURE;

  apr_allocator_max_free_set (allocator, SVN_ALLOCATOR_RECOMMENDED_MAX_FREE);

  pool = svn_pool_create_ex (NULL, allocator);
  apr_allocator_owner_set (allocator, pool);

  received_opts = apr_array_make (pool, SVN_OPT_MAX_OPTIONS, sizeof (int));

  /* Check library versions */
  err = check_lib_versions ();
  if (err)
    return svn_cmdline_handle_exit_error (err, pool, "svnindex: ");

  /* Initialize the FS library. */
  err = svn_fs_initialize (pool);
  if (err)
    return svn_cmdline_handle_exit_error (err, pool, "svnindex: ");

  if (argc <= 1)
    {
      subcommand_help (NULL, NULL, pool);
      svn_pool_destroy (pool);
      return EXIT_FAILURE;
    }

  /* Initialize opt_state. */
  memset (&opt_state, 0, sizeof (opt_state));
  opt_state.start_revision.kind = svn_opt_revision_unspecified;
  opt_state.end_revision.kind = svn_opt_revision_unspecified;

  /* Parse options. */
  apr_getopt_init (&os, pool, argc, argv);
  os->interleave = 1;

  while (1)
    {
      const char *opt_arg;
      const char *utf8_opt_arg;

      /* Parse the next option. */
      apr_err = apr_getopt_long (os, options_table, &opt_id, &opt_arg);
      if (APR_STATUS_IS_EOF (apr_err))
        break;
      else if (apr_err)
        {
          subcommand_help (NULL, NULL, pool);
          svn_pool_destroy (pool);
          return EXIT_FAILURE;
        }

      /* Stash the option code in an array before parsing it. */
      APR_ARRAY_PUSH (received_opts, int) = opt_id;

      switch (opt_id) {
      case 'r':
        {
          if (opt_state.start_revision.kind != svn_opt_revision_unspecified)
            {
              err = svn_error_create
                (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                 _("Multiple revision arguments encountered; "
                   "try '-r M:N' instead of '-r M -r N'"));
              return svn_cmdline_handle_exit_error (err, pool, "svnindex: ");
            }
          if (svn_opt_parse_revision (&(opt_state.start_revision),
                                      &(opt_state.end_revision),
                                      opt_arg, pool) != 0)
            {
              err = svn_utf_cstring_to_utf8 (&utf8_opt_arg, opt_arg,
                                             pool);

              if (! err)
                err = svn_error_createf
                  (SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
                   _("Syntax error in revision argument '%s'"),
                   utf8_opt_arg);
              return svn_cmdline_handle_exit_error (err, pool, "svnindex: ");
            }
        }
        break;
      case 'q':
        opt_state.quiet = TRUE;
        break;
      case 'h':
      case '?':
        opt_state.help = TRUE;
        break;
      case svnindex__version:
        opt_state.version = TRUE;
        opt_state.help = TRUE;
        break;
      case svnindex__db:
        err = svn_utf_cstring_to_utf8 (&opt_state.db, opt_arg,
                                       pool);
        if (err)
          return svn_cmdline_handle_exit_error (err, pool, "svnindex: ");
        break;
      case 'v':
        opt_state.verbose = TRUE;
        break;
      default:
        {
          subcommand_help (NULL, NULL, pool);
          svn_pool_destroy (pool);
          return EXIT_FAILURE;
        }
      }  /* close `switch' */
    }  /* close `while' */
  
  /* 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_subcommand (cmd_table, "help");

  /* If we're not running the `help' subcommand, then look for a
     subcommand in the first argument. */
  if (subcommand == NULL)
    {
      if (os->ind >= os->argc)
        {
          svn_error_clear
            (svn_cmdline_fprintf (stderr, pool,
                                  _("subcommand argument required\n")));
          subcommand_help (NULL, NULL, pool);
          svn_pool_destroy (pool);
          return EXIT_FAILURE;
        }
      else
        {
          const char *first_arg = os->argv[os->ind++];
          subcommand = svn_opt_get_canonical_subcommand (cmd_table, first_arg);
          if (subcommand == NULL)
            {
              const char* first_arg_utf8;
              err = svn_utf_cstring_to_utf8 (&first_arg_utf8, first_arg, pool);
              if (err)
                return svn_cmdline_handle_exit_error (err, pool, "svnindex: ");
              svn_error_clear
                (svn_cmdline_fprintf (stderr, pool,
                                      _("Unknown command: '%s'\n"),
                                      first_arg_utf8));
              subcommand_help (NULL, NULL, pool);
              svn_pool_destroy (pool);
              return EXIT_FAILURE;
            }
        }
    }

  /* If there's a second argument, it's probably the repository.
     Every subcommand except `help' requires one, so we parse it out
     here and store it in opt_state. */
  if (subcommand->cmd_func != subcommand_help)
    {
      err = parse_local_repos_path (os, 
                                    &(opt_state.repository_path), 
                                    pool);
      if(err)
        {
          svn_handle_error2 (err, stderr, FALSE, "svnindex: ");
          svn_opt_subcommand_help (subcommand->name, cmd_table,
                                   options_table, pool);
          svn_error_clear (err);
          svn_pool_destroy (pool);
          return EXIT_FAILURE;
        }

    }


  /* Check that the subcommand wasn't passed any inappropriate options. */
  for (i = 0; i < received_opts->nelts; i++)
    {
      opt_id = APR_ARRAY_IDX (received_opts, i, int);

      /* 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;

      if (! svn_opt_subcommand_takes_option (subcommand, opt_id))
        {
          const char *optstr;
          const apr_getopt_option_t *badopt = 
            svn_opt_get_option_from_code (opt_id, options_table);
          svn_opt_format_option (&optstr, badopt, FALSE, pool);
          svn_error_clear
            (svn_cmdline_fprintf
             (stderr, pool, _("subcommand '%s' doesn't accept option '%s'\n"
                              "Type 'svnindex help %s' for usage.\n"),
              subcommand->name, optstr, subcommand->name));
          svn_pool_destroy (pool);
          return EXIT_FAILURE;
        }
    }

  /* Set up our cancellation support. */
  setup_cancellation_signals (signal_handler);

#ifdef SIGPIPE
  /* Disable SIGPIPE generation for the platforms that have it. */
  apr_signal(SIGPIPE, SIG_IGN);
#endif

  /* Run the subcommand. */
  err = (*subcommand->cmd_func) (os, &opt_state, pool);
  if (err)
    {
      if (err->apr_err == SVN_ERR_CL_ARG_PARSING_ERROR)
        {
          svn_handle_error2 (err, stderr, FALSE, "svnindex: ");
          svn_opt_subcommand_help (subcommand->name, cmd_table,
                                   options_table, pool);
        }
      else
        svn_handle_error2 (err, stderr, FALSE, "svnindex: ");
      svn_error_clear (err);
      svn_pool_destroy (pool);
      return EXIT_FAILURE;
    }
  else
    {
      svn_pool_destroy (pool);
      /* Ensure that everything is written to stdout, so the user will
         see any print errors. */
      err = svn_cmdline_fflush (stdout);
      if (err) {
        svn_handle_error2 (err, stderr, FALSE, "svnindex: ");
        svn_error_clear (err);
        return EXIT_FAILURE;
      }
      return EXIT_SUCCESS;
    }
}
Example #29
0
/*
 * On success, leave *EXIT_CODE untouched and return SVN_NO_ERROR. On error,
 * either return an error to be displayed, or set *EXIT_CODE to non-zero and
 * return SVN_NO_ERROR.
 */
static svn_error_t *
sub_main(int *exit_code, int argc, const char *argv[], apr_pool_t *pool)
{
  enum run_mode run_mode = run_mode_unspecified;
  svn_boolean_t foreground = FALSE;
  apr_socket_t *sock;
  apr_sockaddr_t *sa;
  svn_error_t *err;
  apr_getopt_t *os;
  int opt;
  serve_params_t params;
  const char *arg;
  apr_status_t status;
#ifndef WIN32
  apr_proc_t proc;
#endif
  svn_boolean_t is_multi_threaded;
  enum connection_handling_mode handling_mode = CONNECTION_DEFAULT;
  svn_boolean_t cache_fulltexts = TRUE;
  svn_boolean_t cache_txdeltas = TRUE;
  svn_boolean_t cache_revprops = FALSE;
  svn_boolean_t use_block_read = FALSE;
  apr_uint16_t port = SVN_RA_SVN_PORT;
  const char *host = NULL;
  int family = APR_INET;
  apr_int32_t sockaddr_info_flags = 0;
#if APR_HAVE_IPV6
  svn_boolean_t prefer_v6 = FALSE;
#endif
  svn_boolean_t quiet = FALSE;
  svn_boolean_t is_version = FALSE;
  int mode_opt_count = 0;
  int handling_opt_count = 0;
  const char *config_filename = NULL;
  const char *pid_filename = NULL;
  const char *log_filename = NULL;
  svn_node_kind_t kind;
  apr_size_t min_thread_count = THREADPOOL_MIN_SIZE;
  apr_size_t max_thread_count = THREADPOOL_MAX_SIZE;
#ifdef SVN_HAVE_SASL
  SVN_ERR(cyrus_init(pool));
#endif

  /* Check library versions */
  SVN_ERR(check_lib_versions());

  /* Initialize the FS library. */
  SVN_ERR(svn_fs_initialize(pool));

  SVN_ERR(svn_cmdline__getopt_init(&os, argc, argv, pool));

  params.root = "/";
  params.tunnel = FALSE;
  params.tunnel_user = NULL;
  params.read_only = FALSE;
  params.base = NULL;
  params.cfg = NULL;
  params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_DEFAULT;
  params.logger = NULL;
  params.config_pool = NULL;
  params.authz_pool = NULL;
  params.fs_config = NULL;
  params.vhost = FALSE;
  params.username_case = CASE_ASIS;
  params.memory_cache_size = (apr_uint64_t)-1;
  params.zero_copy_limit = 0;
  params.error_check_interval = 4096;

  while (1)
    {
      status = apr_getopt_long(os, svnserve__options, &opt, &arg);
      if (APR_STATUS_IS_EOF(status))
        break;
      if (status != APR_SUCCESS)
        {
          usage(argv[0], pool);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }
      switch (opt)
        {
        case '6':
#if APR_HAVE_IPV6
          prefer_v6 = TRUE;
#endif
          /* ### Maybe error here if we don't have IPV6 support? */
          break;

        case 'h':
          help(pool);
          return SVN_NO_ERROR;

        case 'q':
          quiet = TRUE;
          break;

        case SVNSERVE_OPT_VERSION:
          is_version = TRUE;
          break;

        case 'd':
          if (run_mode != run_mode_daemon)
            {
              run_mode = run_mode_daemon;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_FOREGROUND:
          foreground = TRUE;
          break;

        case SVNSERVE_OPT_SINGLE_CONN:
          handling_mode = connection_mode_single;
          handling_opt_count++;
          break;

        case 'i':
          if (run_mode != run_mode_inetd)
            {
              run_mode = run_mode_inetd;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_LISTEN_PORT:
          {
            apr_uint64_t val;

            err = svn_cstring_strtoui64(&val, arg, 0, APR_UINT16_MAX, 10);
            if (err)
              return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, err,
                                       _("Invalid port '%s'"), arg);
            port = (apr_uint16_t)val;
          }
          break;

        case SVNSERVE_OPT_LISTEN_HOST:
          host = arg;
          break;

        case 't':
          if (run_mode != run_mode_tunnel)
            {
              run_mode = run_mode_tunnel;
              mode_opt_count++;
            }
          break;

        case SVNSERVE_OPT_TUNNEL_USER:
          params.tunnel_user = arg;
          break;

        case 'X':
          if (run_mode != run_mode_listen_once)
            {
              run_mode = run_mode_listen_once;
              mode_opt_count++;
            }
          break;

        case 'r':
          SVN_ERR(svn_utf_cstring_to_utf8(&params.root, arg, pool));

          SVN_ERR(svn_io_check_resolved_path(params.root, &kind, pool));
          if (kind != svn_node_dir)
            {
              return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
                       _("Root path '%s' does not exist "
                         "or is not a directory"), params.root);
            }

          params.root = svn_dirent_internal_style(params.root, pool);
          SVN_ERR(svn_dirent_get_absolute(&params.root, params.root, pool));
          break;

        case 'R':
          params.read_only = TRUE;
          break;

        case 'T':
          handling_mode = connection_mode_thread;
          handling_opt_count++;
          break;

        case 'c':
          params.compression_level = atoi(arg);
          if (params.compression_level < SVN_DELTA_COMPRESSION_LEVEL_NONE)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_NONE;
          if (params.compression_level > SVN_DELTA_COMPRESSION_LEVEL_MAX)
            params.compression_level = SVN_DELTA_COMPRESSION_LEVEL_MAX;
          break;

        case 'M':
          params.memory_cache_size = 0x100000 * apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_CACHE_TXDELTAS:
          cache_txdeltas = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_FULLTEXTS:
          cache_fulltexts = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CACHE_REVPROPS:
          cache_revprops = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_BLOCK_READ:
          use_block_read = svn_tristate__from_word(arg) == svn_tristate_true;
          break;

        case SVNSERVE_OPT_CLIENT_SPEED:
          {
            apr_size_t bandwidth = (apr_size_t)apr_strtoi64(arg, NULL, 0);

            /* for slower clients, don't try anything fancy */
            if (bandwidth >= 1000)
              {
                /* block other clients for at most 1 ms (at full bandwidth).
                   Note that the send buffer is 16kB anyways. */
                params.zero_copy_limit = bandwidth * 120;

                /* check for aborted connections at the same rate */
                params.error_check_interval = bandwidth * 120;
              }
          }
          break;

        case SVNSERVE_OPT_MIN_THREADS:
          min_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

        case SVNSERVE_OPT_MAX_THREADS:
          max_thread_count = (apr_size_t)apr_strtoi64(arg, NULL, 0);
          break;

#ifdef WIN32
        case SVNSERVE_OPT_SERVICE:
          if (run_mode != run_mode_service)
            {
              run_mode = run_mode_service;
              mode_opt_count++;
            }
          break;
#endif

        case SVNSERVE_OPT_CONFIG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&config_filename, arg, pool));
          config_filename = svn_dirent_internal_style(config_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&config_filename, config_filename,
                                          pool));
          break;

        case SVNSERVE_OPT_PID_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&pid_filename, arg, pool));
          pid_filename = svn_dirent_internal_style(pid_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&pid_filename, pid_filename, pool));
          break;

         case SVNSERVE_OPT_VIRTUAL_HOST:
           params.vhost = TRUE;
           break;

         case SVNSERVE_OPT_LOG_FILE:
          SVN_ERR(svn_utf_cstring_to_utf8(&log_filename, arg, pool));
          log_filename = svn_dirent_internal_style(log_filename, pool);
          SVN_ERR(svn_dirent_get_absolute(&log_filename, log_filename, pool));
          break;

        }
    }

  if (is_version)
    {
      SVN_ERR(version(quiet, pool));
      return SVN_NO_ERROR;
    }

  if (os->ind != argc)
    {
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (mode_opt_count != 1)
    {
      svn_error_clear(svn_cmdline_fputs(
#ifdef WIN32
                      _("You must specify exactly one of -d, -i, -t, "
                        "--service or -X.\n"),
#else
                      _("You must specify exactly one of -d, -i, -t or -X.\n"),
#endif
                       stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  if (handling_opt_count > 1)
    {
      svn_error_clear(svn_cmdline_fputs(
                      _("You may only specify one of -T or --single-thread\n"),
                      stderr, pool));
      usage(argv[0], pool);
      *exit_code = EXIT_FAILURE;
      return SVN_NO_ERROR;
    }

  /* construct object pools */
  is_multi_threaded = handling_mode == connection_mode_thread;
  params.fs_config = apr_hash_make(pool);
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_DELTAS,
                cache_txdeltas ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_FULLTEXTS,
                cache_fulltexts ? "1" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_CACHE_REVPROPS,
                cache_revprops ? "2" :"0");
  svn_hash_sets(params.fs_config, SVN_FS_CONFIG_FSFS_BLOCK_READ,
                use_block_read ? "1" :"0");

  SVN_ERR(svn_repos__config_pool_create(&params.config_pool,
                                        is_multi_threaded,
                                        pool));
  SVN_ERR(svn_repos__authz_pool_create(&params.authz_pool,
                                       params.config_pool,
                                       is_multi_threaded,
                                       pool));

  /* If a configuration file is specified, load it and any referenced
   * password and authorization files. */
  if (config_filename)
    {
      params.base = svn_dirent_dirname(config_filename, pool);

      SVN_ERR(svn_repos__config_pool_get(&params.cfg, NULL,
                                         params.config_pool,
                                         config_filename,
                                         TRUE, /* must_exist */
                                         FALSE, /* names_case_sensitive */
                                         NULL,
                                         pool));
    }

  if (log_filename)
    SVN_ERR(logger__create(&params.logger, log_filename, pool));
  else if (run_mode == run_mode_listen_once)
    SVN_ERR(logger__create_for_stderr(&params.logger, pool));

  if (params.tunnel_user && run_mode != run_mode_tunnel)
    {
      return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
               _("Option --tunnel-user is only valid in tunnel mode"));
    }

  if (run_mode == run_mode_inetd || run_mode == run_mode_tunnel)
    {
      apr_pool_t *connection_pool;
      svn_ra_svn_conn_t *conn;
      svn_stream_t *stdin_stream;
      svn_stream_t *stdout_stream;

      params.tunnel = (run_mode == run_mode_tunnel);
      apr_pool_cleanup_register(pool, pool, apr_pool_cleanup_null,
                                redirect_stdout);

      SVN_ERR(svn_stream_for_stdin(&stdin_stream, pool));
      SVN_ERR(svn_stream_for_stdout(&stdout_stream, pool));

      /* Use a subpool for the connection to ensure that if SASL is used
       * the pool cleanup handlers that call sasl_dispose() (connection_pool)
       * and sasl_done() (pool) are run in the right order. See issue #3664. */
      connection_pool = svn_pool_create(pool);
      conn = svn_ra_svn_create_conn4(NULL, stdin_stream, stdout_stream,
                                     params.compression_level,
                                     params.zero_copy_limit,
                                     params.error_check_interval,
                                     connection_pool);
      err = serve(conn, &params, connection_pool);
      svn_pool_destroy(connection_pool);

      return err;
    }

#ifdef WIN32
  /* If svnserve needs to run as a Win32 service, then we need to
     coordinate with the Service Control Manager (SCM) before
     continuing.  This function call registers the svnserve.exe
     process with the SCM, waits for the "start" command from the SCM
     (which will come very quickly), and confirms that those steps
     succeeded.

     After this call succeeds, the service is free to run.  At some
     point in the future, the SCM will send a message to the service,
     requesting that it stop.  This is translated into a call to
     winservice_notify_stop().  The service is then responsible for
     cleanly terminating.

     We need to do this before actually starting the service logic
     (opening files, sockets, etc.) because the SCM wants you to
     connect *first*, then do your service-specific logic.  If the
     service process takes too long to connect to the SCM, then the
     SCM will decide that the service is busted, and will give up on
     it.
     */
  if (run_mode == run_mode_service)
    {
      err = winservice_start();
      if (err)
        {
          svn_handle_error2(err, stderr, FALSE, "svnserve: ");

          /* This is the most common error.  It means the user started
             svnserve from a shell, and specified the --service
             argument.  svnserve cannot be started, as a service, in
             this way.  The --service argument is valid only valid if
             svnserve is started by the SCM. */
          if (err->apr_err ==
              APR_FROM_OS_ERROR(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT))
            {
              svn_error_clear(svn_cmdline_fprintf(stderr, pool,
                  _("svnserve: The --service flag is only valid if the"
                    " process is started by the Service Control Manager.\n")));
            }

          svn_error_clear(err);
          *exit_code = EXIT_FAILURE;
          return SVN_NO_ERROR;
        }

      /* The service is now in the "starting" state.  Before the SCM will
         consider the service "started", this thread must call the
         winservice_running() function. */
    }
#endif /* WIN32 */

  /* Make sure we have IPV6 support first before giving apr_sockaddr_info_get
     APR_UNSPEC, because it may give us back an IPV6 address even if we can't
     create IPV6 sockets. */

#if APR_HAVE_IPV6
#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status == 0)
    {
      apr_socket_close(sock);
      family = APR_UNSPEC;

      if (prefer_v6)
        {
          if (host == NULL)
            host = "::";
          sockaddr_info_flags = APR_IPV6_ADDR_OK;
        }
      else
        {
          if (host == NULL)
            host = "0.0.0.0";
          sockaddr_info_flags = APR_IPV4_ADDR_OK;
        }
    }
#endif

  status = apr_sockaddr_info_get(&sa, host, family, port,
                                 sockaddr_info_flags, pool);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't get address info"));
    }


#ifdef MAX_SECS_TO_LINGER
  /* ### old APR interface */
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, pool);
#else
  status = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP,
                             pool);
#endif
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't create server socket"));
    }

  /* Prevents "socket in use" errors when server is killed and quickly
   * restarted. */
  status = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't set options on server socket"));
    }

  status = apr_socket_bind(sock, sa);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't bind server socket"));
    }

  status = apr_socket_listen(sock, ACCEPT_BACKLOG);
  if (status)
    {
      return svn_error_wrap_apr(status, _("Can't listen on server socket"));
    }

#if APR_HAS_FORK
  if (run_mode != run_mode_listen_once && !foreground)
    /* ### ignoring errors... */
    apr_proc_detach(APR_PROC_DETACH_DAEMONIZE);

  apr_signal(SIGCHLD, sigchld_handler);
#endif

#ifdef SIGPIPE
  /* Disable SIGPIPE generation for the platforms that have it. */
  apr_signal(SIGPIPE, SIG_IGN);
#endif

#ifdef SIGXFSZ
  /* Disable SIGXFSZ generation for the platforms that have it, otherwise
   * working with large files when compiled against an APR that doesn't have
   * large file support will crash the program, which is uncool. */
  apr_signal(SIGXFSZ, SIG_IGN);
#endif

  if (pid_filename)
    SVN_ERR(write_pid_file(pid_filename, pool));

#ifdef WIN32
  status = apr_os_sock_get(&winservice_svnserve_accept_socket, sock);
  if (status)
    winservice_svnserve_accept_socket = INVALID_SOCKET;

  /* At this point, the service is "running".  Notify the SCM. */
  if (run_mode == run_mode_service)
    winservice_running();
#endif

  /* Configure FS caches for maximum efficiency with svnserve.
   * For pre-forked (i.e. multi-processed) mode of operation,
   * keep the per-process caches smaller than the default.
   * Also, apply the respective command line parameters, if given. */
  {
    svn_cache_config_t settings = *svn_cache_config_get();

    if (params.memory_cache_size != -1)
      settings.cache_size = params.memory_cache_size;

    settings.single_threaded = TRUE;
    if (handling_mode == connection_mode_thread)
      {
#if APR_HAS_THREADS
        settings.single_threaded = FALSE;
#else
        /* No requests will be processed at all
         * (see "switch (handling_mode)" code further down).
         * But if they were, some other synchronization code
         * would need to take care of securing integrity of
         * APR-based structures. That would include our caches.
         */
#endif
      }

    svn_cache_config_set(&settings);
  }

#if APR_HAS_THREADS
  SVN_ERR(svn_root_pools__create(&connection_pools));

  if (handling_mode == connection_mode_thread)
    {
      /* create the thread pool with a valid range of threads */
      if (max_thread_count < 1)
        max_thread_count = 1;
      if (min_thread_count > max_thread_count)
        min_thread_count = max_thread_count;

      status = apr_thread_pool_create(&threads,
                                      min_thread_count,
                                      max_thread_count,
                                      pool);
      if (status)
        {
          return svn_error_wrap_apr(status, _("Can't create thread pool"));
        }

      /* let idle threads linger for a while in case more requests are
         coming in */
      apr_thread_pool_idle_wait_set(threads, THREADPOOL_THREAD_IDLE_LIMIT);

      /* don't queue requests unless we reached the worker thread limit */
      apr_thread_pool_threshold_set(threads, 0);
    }
  else
    {
      threads = NULL;
    }
#endif

  while (1)
    {
      connection_t *connection = NULL;
      SVN_ERR(accept_connection(&connection, sock, &params, handling_mode,
                                pool));
      if (run_mode == run_mode_listen_once)
        {
          err = serve_socket(connection, connection->pool);
          close_connection(connection);
          return err;
        }

      switch (handling_mode)
        {
        case connection_mode_fork:
#if APR_HAS_FORK
          status = apr_proc_fork(&proc, connection->pool);
          if (status == APR_INCHILD)
            {
              /* the child would't listen to the main server's socket */
              apr_socket_close(sock);

              /* serve_socket() logs any error it returns, so ignore it. */
              svn_error_clear(serve_socket(connection, connection->pool));
              close_connection(connection);
              return SVN_NO_ERROR;
            }
          else if (status != APR_INPARENT)
            {
              err = svn_error_wrap_apr(status, "apr_proc_fork");
              logger__log_error(params.logger, err, NULL, NULL);
              svn_error_clear(err);
            }
#endif
          break;

        case connection_mode_thread:
          /* Create a detached thread for each connection.  That's not a
             particularly sophisticated strategy for a threaded server, it's
             little different from forking one process per connection. */
#if APR_HAS_THREADS
          attach_connection(connection);

          status = apr_thread_pool_push(threads, serve_thread, connection,
                                        0, NULL);
          if (status)
            {
              return svn_error_wrap_apr(status, _("Can't push task"));
            }
#endif
          break;

        case connection_mode_single:
          /* Serve one connection at a time. */
          /* serve_socket() logs any error it returns, so ignore it. */
          svn_error_clear(serve_socket(connection, connection->pool));
        }

      close_connection(connection);
    }

  /* NOTREACHED */
}
Example #30
0
int
main(int argc, const char *argv[])
{
  const char *repos_path;
  apr_pool_t *pool;
  svn_boolean_t prop = FALSE, data = FALSE;
  svn_boolean_t quiet = FALSE;
  svn_error_t *err;
  apr_getopt_t *os;
  const apr_getopt_option_t options[] =
    {
      {"data", OPT_DATA, 0, N_("display data reps stats")},
      {"prop", OPT_PROP, 0, N_("display prop reps stats")},
      {"both", OPT_BOTH, 0, N_("display combined (data+prop) reps stats")},
      {"quiet", 'q', 0, N_("no progress (only errors) to stderr")},
      {"help", 'h', 0, N_("display this help")},
      {"version", OPT_VERSION, 0,
       N_("show program version information")},
      {0,             0,  0,  0}
    };

  /* Initialize the app. */
  if (svn_cmdline_init("svn-rep-sharing-stats", stderr) != EXIT_SUCCESS)
    return EXIT_FAILURE;

  /* Create our top-level pool.  Use a separate mutexless allocator,
   * given this application is single threaded.
   */
  pool = apr_allocator_owner_get(svn_pool_create_allocator(FALSE));

  /* Check library versions */
  err = check_lib_versions();
  if (err)
    return svn_cmdline_handle_exit_error(err, pool, "svn-rep-sharing-stats: ");

  err = svn_cmdline__getopt_init(&os, argc, argv, pool);
  if (err)
    return svn_cmdline_handle_exit_error(err, pool, "svn-rep-sharing-stats: ");

  SVN_INT_ERR(check_experimental());

  os->interleave = 1;
  while (1)
    {
      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)
        {
          usage(pool);
          return EXIT_FAILURE;
        }
      switch (opt)
        {
        case OPT_DATA:
          data = TRUE;
          break;
        /* It seems we don't actually rep-share props yet. */
        case OPT_PROP:
          prop = TRUE;
          break;
        case OPT_BOTH:
          data = TRUE;
          prop = TRUE;
          break;
        case 'q':
          quiet = TRUE;
          break;
        case 'h':
          help(options, pool);
          break;
        case OPT_VERSION:
          SVN_INT_ERR(version(pool));
          exit(0);
          break;
        default:
          usage(pool);
          return EXIT_FAILURE;
        }
    }

  /* Exactly 1 non-option argument,
   * and at least one of "--data"/"--prop"/"--both".
   */
  if (os->ind + 1 != argc || (!data && !prop))
    {
      usage(pool);
      return EXIT_FAILURE;
    }

  /* Grab REPOS_PATH from argv. */
  SVN_INT_ERR(svn_utf_cstring_to_utf8(&repos_path, os->argv[os->ind], pool));
  repos_path = svn_dirent_internal_style(repos_path, pool);

  set_up_cancellation();

  /* Do something. */
  SVN_INT_ERR(process(repos_path, prop, data, quiet, pool));

  /* We're done. */

  svn_pool_destroy(pool);
  /* Flush stdout to make sure that the user will see any printing errors. */
  SVN_INT_ERR(svn_cmdline_fflush(stdout));

  return EXIT_SUCCESS;
}