summaryrefslogtreecommitdiff
path: root/subversion/svnserve/logger.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/svnserve/logger.c')
-rw-r--r--subversion/svnserve/logger.c161
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;
+}