diff options
Diffstat (limited to 'subversion/svnserve/logger.c')
-rw-r--r-- | subversion/svnserve/logger.c | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/subversion/svnserve/logger.c b/subversion/svnserve/logger.c new file mode 100644 index 0000000..19b6bd4 --- /dev/null +++ b/subversion/svnserve/logger.c @@ -0,0 +1,161 @@ +/* + * logger.c : Implementation of the SvnServe logger API + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + */ + + + +#define APR_WANT_STRFUNC +#include <apr_want.h> + +#include "svn_error.h" +#include "svn_io.h" +#include "svn_pools.h" +#include "svn_time.h" + +#include "private/svn_mutex.h" + +#include "svn_private_config.h" +#include "logger.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> /* For getpid() */ +#endif + +struct logger_t +{ + /* actual log file / stream object */ + svn_stream_t *stream; + + /* mutex used to serialize access to this structure */ + svn_mutex__t *mutex; + + /* private pool used for temporary allocations */ + apr_pool_t *pool; +}; + +svn_error_t * +logger__create_for_stderr(logger_t **logger, + apr_pool_t *pool) +{ + logger_t *result = apr_pcalloc(pool, sizeof(*result)); + result->pool = svn_pool_create(pool); + + SVN_ERR(svn_stream_for_stderr(&result->stream, pool)); + SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool)); + + *logger = result; + + return SVN_NO_ERROR; +} + +svn_error_t * +logger__create(logger_t **logger, + const char *filename, + apr_pool_t *pool) +{ + logger_t *result = apr_pcalloc(pool, sizeof(*result)); + apr_file_t *file; + + SVN_ERR(svn_io_file_open(&file, filename, + APR_WRITE | APR_CREATE | APR_APPEND, + APR_OS_DEFAULT, pool)); + SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool)); + + result->stream = svn_stream_from_aprfile2(file, FALSE, pool); + result->pool = svn_pool_create(pool); + + *logger = result; + + return SVN_NO_ERROR; +} + +void +logger__log_error(logger_t *logger, + svn_error_t *err, + repository_t *repository, + client_info_t *client_info) +{ + if (logger && err) + { + const char *timestr, *continuation; + const char *user, *repos, *remote_host; + char errbuf[256]; + /* 8192 from MAX_STRING_LEN in from httpd-2.2.4/include/httpd.h */ + char errstr[8192]; + + svn_error_clear(svn_mutex__lock(logger->mutex)); + + timestr = svn_time_to_cstring(apr_time_now(), logger->pool); + remote_host = client_info && client_info->remote_host + ? client_info->remote_host + : "-"; + user = client_info && client_info->user + ? client_info->user + : "-"; + repos = repository && repository->repos_name + ? repository->repos_name + : "-"; + + continuation = ""; + while (err) + { + const char *message = svn_err_best_message(err, errbuf, sizeof(errbuf)); + /* based on httpd-2.2.4/server/log.c:log_error_core */ + apr_size_t len = apr_snprintf(errstr, sizeof(errstr), + "%" APR_PID_T_FMT + " %s %s %s %s ERR%s %s %ld %d ", + getpid(), timestr, remote_host, user, + repos, continuation, + err->file ? err->file : "-", err->line, + err->apr_err); + + len += escape_errorlog_item(errstr + len, message, + sizeof(errstr) - len); + /* Truncate for the terminator (as apr_snprintf does) */ + if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) { + len = sizeof(errstr) - sizeof(APR_EOL_STR); + } + + memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR)); + len += sizeof(APR_EOL_STR) -1; /* add NL, ex terminating NUL */ + + svn_error_clear(svn_stream_write(logger->stream, errstr, &len)); + + continuation = "-"; + err = err->child; + } + + svn_pool_clear(logger->pool); + + svn_error_clear(svn_mutex__unlock(logger->mutex, SVN_NO_ERROR)); + } +} + +svn_error_t * +logger__write(logger_t *logger, + const char *errstr, + apr_size_t len) +{ + SVN_MUTEX__WITH_LOCK(logger->mutex, + svn_stream_write(logger->stream, errstr, &len)); + return SVN_NO_ERROR; +} |