198 lines
4.4 KiB
C
198 lines
4.4 KiB
C
|
|
/*-
|
|
* Copyright (c) 2016, Babak Farrokhi
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice, this
|
|
* list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "logfile.h"
|
|
|
|
#ifdef __linux__
|
|
#define _PROGNAME program_invocation_short_name
|
|
#else
|
|
#define _PROGNAME getprogname()
|
|
#endif /* __linux__ */
|
|
|
|
/*
|
|
* create/open given logfile and initialize appropriate struct
|
|
*/
|
|
log_t *
|
|
log_open(const char *path, mode_t mode)
|
|
{
|
|
log_t *lh;
|
|
struct stat sb;
|
|
char *filename;
|
|
int fd;
|
|
|
|
if (path == NULL) {
|
|
asprintf(&filename, "%s/%s.log", LOGPATH, _PROGNAME);
|
|
} else {
|
|
filename = (char *)path;
|
|
}
|
|
|
|
/*
|
|
* try to create / append the file and make sure it is correctly
|
|
* created
|
|
*/
|
|
if ((fd = open(filename, O_WRONLY | O_APPEND | O_CREAT | O_SYNC, mode)) == -1)
|
|
return (NULL);
|
|
if (flock(fd, LOCK_EX) == -1) {
|
|
close(fd);
|
|
return (NULL);
|
|
}
|
|
if (stat(filename, &sb) == -1) {
|
|
close(fd);
|
|
return (NULL);
|
|
}
|
|
/* initialize data structure */
|
|
lh = calloc(1, sizeof(log_t));
|
|
|
|
lh->fd = fd;
|
|
lh->dev = sb.st_dev;
|
|
lh->ino = sb.st_ino;
|
|
lh->mode = sb.st_mode;
|
|
strncpy(lh->path, filename, strnlen(filename, MAXPATHLEN + 1));
|
|
|
|
return (lh);
|
|
}
|
|
|
|
/*
|
|
* close logfile handle and free up allocated struct
|
|
*/
|
|
void
|
|
log_close(const log_t *log)
|
|
{
|
|
if (!log_isopen(log))
|
|
return;
|
|
|
|
close(log->fd);
|
|
free((void *)log);
|
|
}
|
|
|
|
/*
|
|
* check whether or not the logfile is opened
|
|
*/
|
|
inline bool
|
|
log_isopen(const log_t *log)
|
|
{
|
|
if (log == NULL)
|
|
return (false);
|
|
return (log->fd != -1);
|
|
}
|
|
|
|
/*
|
|
* close and open logfile, used when a HUP signal is received (mosly in case of log roration)
|
|
*/
|
|
void
|
|
log_reopen(log_t **log)
|
|
{
|
|
log_t *newlog;
|
|
|
|
if (!log_isopen(*log))
|
|
return;
|
|
|
|
newlog = malloc(sizeof(log_t));
|
|
memcpy(newlog, *log, sizeof(log_t));
|
|
log_close(*log);
|
|
*log = log_open(newlog->path, newlog->mode);
|
|
free(newlog);
|
|
}
|
|
|
|
/*
|
|
* printf given text into logfile
|
|
*/
|
|
|
|
void
|
|
log_printf(const log_t *log, const char *format,...)
|
|
{
|
|
if (!log_isopen(log))
|
|
return;
|
|
|
|
va_list args;
|
|
char *message;
|
|
char *newline = "\n";
|
|
|
|
va_start(args, format);
|
|
vasprintf(&message, format, args);
|
|
va_end(args);
|
|
|
|
write(log->fd, message, strnlen(message, MAX_MSG_SIZE));
|
|
write(log->fd, newline, sizeof(*newline));
|
|
|
|
free(message);
|
|
}
|
|
|
|
/*
|
|
* printf into a logfile with timestamp prefix
|
|
*/
|
|
void
|
|
log_tsprintf(const log_t *log, const char *format,...)
|
|
{
|
|
if (!log_isopen(log))
|
|
return;
|
|
|
|
va_list args;
|
|
char *message;
|
|
char s_time[30];
|
|
time_t now;
|
|
struct tm *ltime;
|
|
size_t tsize;
|
|
char *newline = "\n";
|
|
|
|
va_start(args, format);
|
|
vasprintf(&message, format, args);
|
|
va_end(args);
|
|
|
|
now = time(NULL);
|
|
ltime = localtime(&now);
|
|
tsize = strftime(s_time, sizeof(s_time), "%Y-%m-%d %T %Z - ", ltime);
|
|
|
|
write(log->fd, s_time, tsize);
|
|
write(log->fd, message, strnlen(message, MAX_MSG_SIZE));
|
|
write(log->fd, newline, sizeof(*newline));
|
|
|
|
free(message);
|
|
}
|
|
|
|
/*
|
|
* check integrity of logfile with comparing filesystem stat with our use-specified settings
|
|
*/
|
|
bool
|
|
log_verify(const log_t *log)
|
|
{
|
|
struct stat sb;
|
|
|
|
if (log == NULL || log->fd == -1) {
|
|
errno = EINVAL;
|
|
return (false);
|
|
}
|
|
if (fstat(log->fd, &sb) == -1)
|
|
return (false);
|
|
|
|
if (log->ino != sb.st_ino || log->dev != sb.st_dev || log->mode != sb.st_mode) {
|
|
errno = EINVAL;
|
|
return (false);
|
|
}
|
|
return true;
|
|
}
|