2011-12-19 18:52:50 +04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/resource.h>
|
|
|
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include "compiler.h"
|
2013-01-09 17:02:47 +04:00
|
|
|
#include "asm/types.h"
|
2011-12-19 18:52:50 +04:00
|
|
|
#include "util.h"
|
2013-11-06 17:21:11 +04:00
|
|
|
#include "cr_options.h"
|
2013-11-05 20:17:47 +04:00
|
|
|
#include "servicefd.h"
|
2011-12-19 18:52:50 +04:00
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
#define DEFAULT_LOGFD STDERR_FILENO
|
2011-12-19 18:52:50 +04:00
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
static unsigned int current_loglevel = DEFAULT_LOGLEVEL;
|
|
|
|
|
2012-05-02 14:42:00 +04:00
|
|
|
static char buffer[PAGE_SIZE];
|
|
|
|
static char buf_off = 0;
|
|
|
|
|
2012-10-03 02:18:01 +04:00
|
|
|
static struct timeval start;
|
|
|
|
/*
|
|
|
|
* Manual buf len as sprintf will _always_ put '\0' at the
|
|
|
|
* and, but we want a "constant" pid to be there on restore
|
|
|
|
*/
|
|
|
|
#define TS_BUF_OFF 12
|
|
|
|
|
|
|
|
static void timediff(struct timeval *from, struct timeval *to)
|
|
|
|
{
|
|
|
|
to->tv_sec -= from->tv_sec;
|
|
|
|
if (to->tv_usec >= from->tv_usec)
|
|
|
|
to->tv_usec -= from->tv_usec;
|
|
|
|
else {
|
|
|
|
to->tv_sec--;
|
|
|
|
to->tv_usec += 1000000 - from->tv_usec;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_ts(void)
|
|
|
|
{
|
|
|
|
struct timeval t;
|
|
|
|
|
|
|
|
gettimeofday(&t, NULL);
|
|
|
|
timediff(&start, &t);
|
|
|
|
snprintf(buffer, TS_BUF_OFF,
|
|
|
|
"(%02u.%06u)", (unsigned)t.tv_sec, (unsigned)t.tv_usec);
|
|
|
|
buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */
|
|
|
|
}
|
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
int log_get_fd(void)
|
2011-12-19 18:52:50 +04:00
|
|
|
{
|
2013-01-11 18:16:20 +04:00
|
|
|
int fd = get_service_fd(LOG_FD_OFF);
|
|
|
|
|
|
|
|
return fd < 0 ? DEFAULT_LOGFD : fd;
|
2011-12-19 18:52:50 +04:00
|
|
|
}
|
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
int log_init(const char *output)
|
2011-12-19 18:52:50 +04:00
|
|
|
{
|
2013-11-15 23:04:28 +04:00
|
|
|
int new_logfd, fd;
|
2012-09-02 01:02:30 +04:00
|
|
|
|
2012-10-03 02:18:01 +04:00
|
|
|
gettimeofday(&start, NULL);
|
|
|
|
buf_off = TS_BUF_OFF;
|
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
if (output) {
|
2013-11-15 23:04:28 +04:00
|
|
|
new_logfd = open(output, O_CREAT|O_TRUNC|O_WRONLY|O_APPEND, 0600);
|
2012-03-01 18:52:42 +04:00
|
|
|
if (new_logfd < 0) {
|
|
|
|
pr_perror("Can't create log file %s", output);
|
2011-12-19 18:52:50 +04:00
|
|
|
return -1;
|
|
|
|
}
|
2013-04-12 02:16:58 +04:00
|
|
|
} else {
|
2013-01-11 18:16:20 +04:00
|
|
|
new_logfd = dup(DEFAULT_LOGFD);
|
2013-04-12 02:16:58 +04:00
|
|
|
if (new_logfd < 0) {
|
|
|
|
pr_perror("Can't dup log file");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 15:44:13 +04:00
|
|
|
|
2013-01-11 18:16:20 +04:00
|
|
|
fd = install_service_fd(LOG_FD_OFF, new_logfd);
|
|
|
|
close(new_logfd);
|
|
|
|
if (fd < 0)
|
|
|
|
goto err;
|
2011-12-19 18:52:50 +04:00
|
|
|
|
|
|
|
return 0;
|
2012-03-01 18:52:42 +04:00
|
|
|
|
2012-01-10 16:39:00 +04:00
|
|
|
err:
|
2012-03-01 18:52:42 +04:00
|
|
|
pr_perror("Log engine failure, can't duplicate descriptor");
|
2012-01-10 16:39:00 +04:00
|
|
|
return -1;
|
2011-12-19 18:52:50 +04:00
|
|
|
}
|
|
|
|
|
2012-05-02 14:42:00 +04:00
|
|
|
int log_init_by_pid(void)
|
|
|
|
{
|
|
|
|
char path[PATH_MAX];
|
|
|
|
|
2012-10-03 02:18:01 +04:00
|
|
|
/*
|
|
|
|
* reset buf_off as this fn is called on each fork while
|
|
|
|
* restoring process tree
|
|
|
|
*/
|
|
|
|
|
|
|
|
buf_off = TS_BUF_OFF;
|
|
|
|
|
2012-05-02 14:42:00 +04:00
|
|
|
if (!opts.log_file_per_pid) {
|
2012-10-03 02:18:01 +04:00
|
|
|
buf_off += snprintf(buffer + buf_off, PAGE_SIZE - buf_off, "%6d: ", getpid());
|
2012-05-02 14:42:00 +04:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!opts.output)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
snprintf(path, PATH_MAX, "%s.%d", opts.output, getpid());
|
|
|
|
|
|
|
|
return log_init(path);
|
|
|
|
}
|
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
void log_fini(void)
|
2011-12-19 18:52:50 +04:00
|
|
|
{
|
2013-01-11 18:16:20 +04:00
|
|
|
close_service_fd(LOG_FD_OFF);
|
2012-09-02 01:02:30 +04:00
|
|
|
}
|
|
|
|
|
2012-03-01 18:52:42 +04:00
|
|
|
void log_set_loglevel(unsigned int level)
|
2012-02-17 22:51:23 +04:00
|
|
|
{
|
|
|
|
if (!level)
|
2012-03-01 18:52:42 +04:00
|
|
|
current_loglevel = DEFAULT_LOGLEVEL;
|
2012-02-17 22:51:23 +04:00
|
|
|
else
|
2012-03-01 18:52:42 +04:00
|
|
|
current_loglevel = level;
|
2012-02-17 22:51:23 +04:00
|
|
|
}
|
|
|
|
|
2012-09-03 14:44:01 +04:00
|
|
|
unsigned int log_get_loglevel(void)
|
|
|
|
{
|
|
|
|
return current_loglevel;
|
|
|
|
}
|
|
|
|
|
2013-01-14 14:26:18 +04:00
|
|
|
static void __print_on_level(unsigned int loglevel, const char *format, va_list params)
|
2012-02-17 12:17:00 +04:00
|
|
|
{
|
2012-05-02 14:42:00 +04:00
|
|
|
int fd, size, ret, off;
|
2012-03-01 18:52:42 +04:00
|
|
|
|
|
|
|
if (unlikely(loglevel == LOG_MSG)) {
|
|
|
|
fd = STDOUT_FILENO;
|
2012-11-06 13:37:15 +04:00
|
|
|
off = buf_off;
|
2012-03-01 18:52:42 +04:00
|
|
|
} else {
|
|
|
|
if (loglevel > current_loglevel)
|
|
|
|
return;
|
2013-01-11 18:16:20 +04:00
|
|
|
fd = log_get_fd();
|
2012-10-03 19:22:23 +04:00
|
|
|
print_ts();
|
2012-11-06 13:37:15 +04:00
|
|
|
off = 0;
|
2012-10-03 20:55:23 +04:00
|
|
|
}
|
2012-10-03 02:18:01 +04:00
|
|
|
|
2013-01-14 14:26:18 +04:00
|
|
|
size = vsnprintf(buffer + buf_off, PAGE_SIZE - buf_off, format, params);
|
2012-05-02 14:42:00 +04:00
|
|
|
size += buf_off;
|
|
|
|
|
|
|
|
while (off < size) {
|
|
|
|
ret = write(fd, buffer + off, size - off);
|
|
|
|
if (ret <= 0)
|
|
|
|
break;
|
|
|
|
off += ret;
|
|
|
|
}
|
2012-02-17 12:17:00 +04:00
|
|
|
}
|
2013-01-14 14:26:18 +04:00
|
|
|
|
|
|
|
void print_on_level(unsigned int loglevel, const char *format, ...)
|
|
|
|
{
|
|
|
|
va_list params;
|
|
|
|
|
|
|
|
va_start(params, format);
|
|
|
|
__print_on_level(loglevel, format, params);
|
|
|
|
va_end(params);
|
|
|
|
}
|
2013-09-16 15:45:01 +04:00
|
|
|
|
2013-11-20 14:26:41 +04:00
|
|
|
int write_pidfile(int pid)
|
2013-09-16 15:45:01 +04:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
|
2013-11-20 14:26:41 +04:00
|
|
|
fd = open(opts.pidfile, O_WRONLY | O_TRUNC | O_CREAT, 0600);
|
2013-09-16 15:45:01 +04:00
|
|
|
if (fd == -1) {
|
2013-11-20 14:26:41 +04:00
|
|
|
pr_perror("Can't open %s", opts.pidfile);
|
2013-09-16 15:45:01 +04:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
dprintf(fd, "%d", pid);
|
|
|
|
close(fd);
|
|
|
|
return 0;
|
|
|
|
}
|