1289177Speter/* 2289177Speter * logger.c : Implementation of the SvnServe logger API 3289177Speter * 4289177Speter * ==================================================================== 5289177Speter * Licensed to the Apache Software Foundation (ASF) under one 6289177Speter * or more contributor license agreements. See the NOTICE file 7289177Speter * distributed with this work for additional information 8289177Speter * regarding copyright ownership. The ASF licenses this file 9289177Speter * to you under the Apache License, Version 2.0 (the 10289177Speter * "License"); you may not use this file except in compliance 11289177Speter * with the License. You may obtain a copy of the License at 12289177Speter * 13289177Speter * http://www.apache.org/licenses/LICENSE-2.0 14289177Speter * 15289177Speter * Unless required by applicable law or agreed to in writing, 16289177Speter * software distributed under the License is distributed on an 17289177Speter * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18289177Speter * KIND, either express or implied. See the License for the 19289177Speter * specific language governing permissions and limitations 20289177Speter * under the License. 21289177Speter * ==================================================================== 22289177Speter */ 23289177Speter 24289177Speter 25289177Speter 26289177Speter#define APR_WANT_STRFUNC 27289177Speter#include <apr_want.h> 28289177Speter 29289177Speter#include "svn_error.h" 30289177Speter#include "svn_io.h" 31289177Speter#include "svn_pools.h" 32289177Speter#include "svn_time.h" 33289177Speter 34289177Speter#include "private/svn_mutex.h" 35289177Speter 36289177Speter#include "svn_private_config.h" 37289177Speter#include "logger.h" 38289177Speter 39289177Speter#ifdef HAVE_UNISTD_H 40289177Speter#include <unistd.h> /* For getpid() */ 41289177Speter#endif 42289177Speter 43289177Speterstruct logger_t 44289177Speter{ 45289177Speter /* actual log file / stream object */ 46289177Speter svn_stream_t *stream; 47289177Speter 48289177Speter /* mutex used to serialize access to this structure */ 49289177Speter svn_mutex__t *mutex; 50289177Speter 51289177Speter /* private pool used for temporary allocations */ 52289177Speter apr_pool_t *pool; 53289177Speter}; 54289177Speter 55289177Spetersvn_error_t * 56289177Speterlogger__create_for_stderr(logger_t **logger, 57289177Speter apr_pool_t *pool) 58289177Speter{ 59289177Speter logger_t *result = apr_pcalloc(pool, sizeof(*result)); 60289177Speter result->pool = svn_pool_create(pool); 61289177Speter 62289177Speter SVN_ERR(svn_stream_for_stderr(&result->stream, pool)); 63289177Speter SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool)); 64289177Speter 65289177Speter *logger = result; 66289177Speter 67289177Speter return SVN_NO_ERROR; 68289177Speter} 69289177Speter 70289177Spetersvn_error_t * 71289177Speterlogger__create(logger_t **logger, 72289177Speter const char *filename, 73289177Speter apr_pool_t *pool) 74289177Speter{ 75289177Speter logger_t *result = apr_pcalloc(pool, sizeof(*result)); 76289177Speter apr_file_t *file; 77289177Speter 78289177Speter SVN_ERR(svn_io_file_open(&file, filename, 79289177Speter APR_WRITE | APR_CREATE | APR_APPEND, 80289177Speter APR_OS_DEFAULT, pool)); 81289177Speter SVN_ERR(svn_mutex__init(&result->mutex, TRUE, pool)); 82289177Speter 83289177Speter result->stream = svn_stream_from_aprfile2(file, FALSE, pool); 84289177Speter result->pool = svn_pool_create(pool); 85289177Speter 86289177Speter *logger = result; 87289177Speter 88289177Speter return SVN_NO_ERROR; 89289177Speter} 90289177Speter 91289177Spetervoid 92289177Speterlogger__log_error(logger_t *logger, 93289177Speter svn_error_t *err, 94289177Speter repository_t *repository, 95289177Speter client_info_t *client_info) 96289177Speter{ 97289177Speter if (logger && err) 98289177Speter { 99289177Speter const char *timestr, *continuation; 100289177Speter const char *user, *repos, *remote_host; 101289177Speter char errbuf[256]; 102289177Speter /* 8192 from MAX_STRING_LEN in from httpd-2.2.4/include/httpd.h */ 103289177Speter char errstr[8192]; 104289177Speter 105289177Speter svn_error_clear(svn_mutex__lock(logger->mutex)); 106289177Speter 107289177Speter timestr = svn_time_to_cstring(apr_time_now(), logger->pool); 108289177Speter remote_host = client_info && client_info->remote_host 109289177Speter ? client_info->remote_host 110289177Speter : "-"; 111289177Speter user = client_info && client_info->user 112289177Speter ? client_info->user 113289177Speter : "-"; 114289177Speter repos = repository && repository->repos_name 115289177Speter ? repository->repos_name 116289177Speter : "-"; 117289177Speter 118289177Speter continuation = ""; 119289177Speter while (err) 120289177Speter { 121289177Speter const char *message = svn_err_best_message(err, errbuf, sizeof(errbuf)); 122289177Speter /* based on httpd-2.2.4/server/log.c:log_error_core */ 123289177Speter apr_size_t len = apr_snprintf(errstr, sizeof(errstr), 124289177Speter "%" APR_PID_T_FMT 125289177Speter " %s %s %s %s ERR%s %s %ld %d ", 126289177Speter getpid(), timestr, remote_host, user, 127289177Speter repos, continuation, 128289177Speter err->file ? err->file : "-", err->line, 129289177Speter err->apr_err); 130289177Speter 131289177Speter len += escape_errorlog_item(errstr + len, message, 132289177Speter sizeof(errstr) - len); 133289177Speter /* Truncate for the terminator (as apr_snprintf does) */ 134289177Speter if (len > sizeof(errstr) - sizeof(APR_EOL_STR)) { 135289177Speter len = sizeof(errstr) - sizeof(APR_EOL_STR); 136289177Speter } 137289177Speter 138289177Speter memcpy(errstr + len, APR_EOL_STR, sizeof(APR_EOL_STR)); 139289177Speter len += sizeof(APR_EOL_STR) -1; /* add NL, ex terminating NUL */ 140289177Speter 141289177Speter svn_error_clear(svn_stream_write(logger->stream, errstr, &len)); 142289177Speter 143289177Speter continuation = "-"; 144289177Speter err = err->child; 145289177Speter } 146289177Speter 147289177Speter svn_pool_clear(logger->pool); 148289177Speter 149289177Speter svn_error_clear(svn_mutex__unlock(logger->mutex, SVN_NO_ERROR)); 150289177Speter } 151289177Speter} 152289177Speter 153289177Spetersvn_error_t * 154289177Speterlogger__write(logger_t *logger, 155289177Speter const char *errstr, 156289177Speter apr_size_t len) 157289177Speter{ 158289177Speter SVN_MUTEX__WITH_LOCK(logger->mutex, 159289177Speter svn_stream_write(logger->stream, errstr, &len)); 160289177Speter return SVN_NO_ERROR; 161289177Speter} 162