diff options
Diffstat (limited to 'src/server/log.c')
-rw-r--r-- | src/server/log.c | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/src/server/log.c b/src/server/log.c new file mode 100644 index 0000000..6d77dc5 --- /dev/null +++ b/src/server/log.c @@ -0,0 +1,183 @@ +/* + * This file is part of the Distributed Network Block Device 3 + * + * Copyright(c) 2011-2012 Simon Rettberg + * + * This file may be licensed under the terms of of the + * GNU General Public License Version 2 (the ``GPL''). + * + * Software distributed under the License is distributed + * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either + * express or implied. See the GPL for the specific language + * governing rights and limitations. + * + * You should have received a copy of the GPL along with this + * program. If not, go to http://www.gnu.org/licenses/gpl.html + * or write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "log.h" +#include <stdarg.h> +#include <pthread.h> +#include <time.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <errno.h> + +#define LINE_LEN (800) + +static pthread_mutex_t logLock = PTHREAD_MUTEX_INITIALIZER; +static logmask_t maskFile = 31; +static logmask_t maskCon = 15; + +static char *logFile = NULL; +static int logFd = -1; + + +static int writeLevel(char *buffer, logmask_t level); + + +void log_setFileMask(logmask_t mask) +{ + maskFile = mask; +} + +void log_setConsoleMask(logmask_t mask) +{ + maskCon = mask; +} + +bool log_openLogFile(const char *path) +{ + pthread_mutex_lock( &logLock ); + if ( logFd >= 0 ) { + close( logFd ); + } + if ( path == NULL && logFile == NULL ) + goto unlock; + if ( path != NULL ) { + free( logFile ); + logFile = strdup( path ); + } + logFd = open( logFile, O_WRONLY | O_CREAT | O_APPEND, 0644 ); + if ( logFd < 0 ) + goto unlock; +unlock: ; + pthread_mutex_unlock( &logLock ); + return logFd >= 0; +} + +void logadd(const logmask_t mask, const char *fmt, ...) +{ + if ( ( (maskFile | maskCon) & mask ) == 0 ) + return; + va_list ap; + int ret; + time_t rawtime; + struct tm *timeinfo; + char buffer[LINE_LEN]; + + time( &rawtime ); + timeinfo = localtime( &rawtime ); + size_t offset = strftime( buffer, LINE_LEN, "[%d.%m. %H:%M:%S] ", timeinfo ); + offset += writeLevel( buffer + offset, mask ); + va_start( ap, fmt ); + ret = vsnprintf( buffer + offset, LINE_LEN - offset, fmt, ap ); + va_end( ap ); + if ( ret < 0 ) return; + ret += offset; + if ( ret + 1 >= LINE_LEN ) { + buffer[LINE_LEN-2] = '\0'; + ret = LINE_LEN - 2; + } + if ( ret > 0 && buffer[ret-1] != '\n' ) { + buffer[ret++] = '\n'; + buffer[ret] = '\0'; + } + if ( maskFile & mask ) { + pthread_mutex_lock( &logLock ); + if ( logFd >= 0 ) { + int done = 0; + while (done < ret ) { + const int wr = write( logFd, buffer + done, ret - done ); + if ( wr < 0 ) { + printf( "Logging to file failed! (errno=%d)\n", errno ); + break; + } + done += wr; + } + } + pthread_mutex_unlock( &logLock ); + } + if ( maskCon & mask ) { + fputs( buffer, stdout ); + fflush( stdout ); + } +} + +bool log_fetch(char *buffer, int size) +{ + if ( logFile == NULL || size <= 1 ) + return false; + int fd = open( logFile, O_RDONLY ); + if ( fd < 0 ) + return false; + off_t off = lseek( fd, 0, SEEK_END ); + if ( off == (off_t)-1 ) { + close( fd ); + return false; + } + if ( (off_t)size <= off ) { + off -= size; + } else { + off = 0; + } + ssize_t ret = pread( fd, buffer, size - 1, off ); + close( fd ); + if ( ret < 0 ) + return false; + buffer[ret] = '\0'; + return true; +} + +static int writeLevel(char *buffer, logmask_t level) +{ + const char *word; + char *dest = buffer; + switch ( level ) { + case LOG_ERROR: + word = "ERROR"; + break; + case LOG_WARNING: + word = "WARNING"; + break; + case LOG_MINOR: + word = "Warning"; + break; + case LOG_INFO: + word = "Info"; + break; + case LOG_DEBUG1: + word = "DEBUG1"; + break; + case LOG_DEBUG2: + word = "DEBUG2"; + break; + default: + word = "!?!?!?"; + break; + } + while ( ( *dest++ = *word++ ) ); + *--dest = ':'; + *++dest = ' '; + return (int)( dest - buffer ) + 1; +} + |