| /* |
| * 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; |
| } |
| |
| static void |
| log_message(logger_t *logger, |
| const svn_error_t *err, |
| const char *prefix, |
| repository_t *repository, |
| client_info_t *client_info) |
| { |
| if (logger && err) |
| { |
| const char *timestr, *continuation; |
| const char *user, *repos, *remote_host; |
| |
| /* 8192 from MAX_STRING_LEN in from httpd-2.2.4/include/httpd.h */ |
| const apr_size_t errstr_size = 8192; |
| char *errstr = apr_palloc(logger->pool, errstr_size); |
| |
| 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) |
| { |
| char errbuf[256]; |
| 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, errstr_size, |
| "%" APR_PID_T_FMT |
| " %s %s %s %s %s%s %s %ld %d ", |
| getpid(), timestr, remote_host, user, |
| repos, prefix, continuation, |
| err->file ? err->file : "-", err->line, |
| err->apr_err); |
| |
| len += escape_errorlog_item(errstr + len, message, |
| errstr_size - len); |
| /* Truncate for the terminator (as apr_snprintf does) */ |
| if (len > errstr_size - sizeof(APR_EOL_STR)) { |
| len = errstr_size - 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)); |
| } |
| } |
| |
| void |
| logger__log_error(logger_t *logger, |
| const svn_error_t *err, |
| repository_t *repository, |
| client_info_t *client_info) |
| { |
| log_message(logger, err, "ERR", repository, client_info); |
| } |
| |
| void |
| logger__log_warning(logger_t *logger, |
| const svn_error_t *err, |
| repository_t *repository, |
| client_info_t *client_info) |
| { |
| log_message(logger, err, "WARN", repository, client_info); |
| } |
| |
| 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; |
| } |