LCOV - code coverage report
Current view: top level - crtools - log.c (source / functions) Hit Total Coverage
Test: crtools.info Lines: 67 86 77.9 %
Date: 2012-12-28 Functions: 8 9 88.9 %
Branches: 23 38 60.5 %

           Branch data     Line data    Source code
       1                 :            : #include <stdlib.h>
       2                 :            : #include <stdio.h>
       3                 :            : #include <stdarg.h>
       4                 :            : #include <errno.h>
       5                 :            : #include <unistd.h>
       6                 :            : #include <stdbool.h>
       7                 :            : #include <limits.h>
       8                 :            : 
       9                 :            : #include <sys/types.h>
      10                 :            : #include <sys/time.h>
      11                 :            : #include <sys/resource.h>
      12                 :            : 
      13                 :            : #include <fcntl.h>
      14                 :            : 
      15                 :            : #include "compiler.h"
      16                 :            : #include "types.h"
      17                 :            : #include "util.h"
      18                 :            : #include "crtools.h"
      19                 :            : 
      20                 :            : #define DEFAULT_LOGFD           STDERR_FILENO
      21                 :            : 
      22                 :            : static unsigned int current_loglevel = DEFAULT_LOGLEVEL;
      23                 :            : static int current_logfd = DEFAULT_LOGFD;
      24                 :            : static int logdir = -1;
      25                 :            : 
      26                 :            : static char buffer[PAGE_SIZE];
      27                 :            : static char buf_off = 0;
      28                 :            : 
      29                 :            : static struct timeval start;
      30                 :            : /*
      31                 :            :  * Manual buf len as sprintf will _always_ put '\0' at the
      32                 :            :  * and, but we want a "constant" pid to be there on restore
      33                 :            :  */
      34                 :            : #define TS_BUF_OFF      12
      35                 :            : 
      36                 :            : static void timediff(struct timeval *from, struct timeval *to)
      37                 :            : {
      38                 :     203127 :         to->tv_sec -= from->tv_sec;
      39         [ +  + ]:     203127 :         if (to->tv_usec >= from->tv_usec)
      40                 :     166021 :                 to->tv_usec -= from->tv_usec;
      41                 :            :         else {
      42                 :      37106 :                 to->tv_sec--;
      43                 :      37106 :                 to->tv_usec += 1000000 - from->tv_usec;
      44                 :            :         }
      45                 :            : }
      46                 :            : 
      47                 :     203127 : static void print_ts(void)
      48                 :            : {
      49                 :            :         struct timeval t;
      50                 :            : 
      51                 :     203127 :         gettimeofday(&t, NULL);
      52                 :            :         timediff(&start, &t);
      53                 :     406254 :         snprintf(buffer, TS_BUF_OFF,
      54                 :     406254 :                         "(%02u.%06u)", (unsigned)t.tv_sec, (unsigned)t.tv_usec);
      55                 :     203127 :         buffer[TS_BUF_OFF - 1] = ' '; /* kill the '\0' produced by snprintf */
      56                 :     203127 : }
      57                 :            : 
      58                 :            : 
      59                 :            : 
      60                 :       1157 : int log_get_fd(void)
      61                 :            : {
      62                 :       1157 :         return current_logfd;
      63                 :            : }
      64                 :            : 
      65                 :        547 : int log_init(const char *output)
      66                 :            : {
      67                 :            :         int new_logfd, sfd, dfd;
      68                 :            : 
      69                 :        547 :         gettimeofday(&start, NULL);
      70                 :        547 :         buf_off = TS_BUF_OFF;
      71                 :            : 
      72                 :        547 :         dfd = get_service_fd(LOG_DIR_FD_OFF);
      73         [ -  + ]:        547 :         if (dfd < 0) {
      74                 :          0 :                 pr_msg("Can't obtain logfd");
      75                 :          0 :                 goto err;
      76                 :            :         }
      77                 :            : 
      78         [ +  - ]:        547 :         if (logdir < 0) {
      79                 :            :                 int tmp;
      80                 :        547 :                 tmp = open(".", O_RDONLY);
      81         [ -  + ]:        547 :                 if (tmp == -1) {
      82                 :          0 :                         pr_perror("Can't open a current directory");
      83                 :          0 :                         return -1;
      84                 :            :                 }
      85                 :            : 
      86         [ +  - ]:        547 :                 if (reopen_fd_as(dfd, tmp) < 0)
      87                 :            :                         return -1;
      88                 :            : 
      89                 :        547 :                 logdir = dfd;
      90                 :            :         }
      91                 :            : 
      92                 :        547 :         sfd = get_service_fd(LOG_FD_OFF);
      93         [ -  + ]:        547 :         if (sfd < 0) {
      94                 :          0 :                 pr_msg("Can't obtain logfd");
      95                 :          0 :                 goto err;
      96                 :            :         }
      97                 :            : 
      98         [ +  + ]:        547 :         if (output) {
      99                 :        546 :                 new_logfd = openat(logdir, output,
     100                 :            :                                         O_CREAT | O_TRUNC | O_WRONLY | O_APPEND, 0600);
     101         [ -  + ]:        546 :                 if (new_logfd < 0) {
     102                 :          0 :                         pr_perror("Can't create log file %s", output);
     103                 :          0 :                         return -1;
     104                 :            :                 }
     105                 :            : 
     106         [ -  + ]:        546 :                 if (sfd == current_logfd)
     107                 :          0 :                         close(sfd);
     108                 :            : 
     109         [ +  - ]:        546 :                 if (reopen_fd_as(sfd, new_logfd) < 0)
     110                 :            :                         goto err;
     111                 :            :         } else {
     112                 :          1 :                 new_logfd = dup2(DEFAULT_LOGFD, sfd);
     113         [ -  + ]:          1 :                 if (new_logfd < 0) {
     114                 :          0 :                         pr_perror("Dup %d -> %d failed", DEFAULT_LOGFD, sfd);
     115                 :          0 :                         goto err;
     116                 :            :                 }
     117                 :            :         }
     118                 :            : 
     119                 :        547 :         current_logfd = sfd;
     120                 :            : 
     121                 :        547 :         return 0;
     122                 :            : 
     123                 :            : err:
     124                 :          0 :         pr_perror("Log engine failure, can't duplicate descriptor");
     125                 :        547 :         return -1;
     126                 :            : }
     127                 :            : 
     128                 :        483 : int log_init_by_pid(void)
     129                 :            : {
     130                 :            :         char path[PATH_MAX];
     131                 :            : 
     132                 :            :         /*
     133                 :            :          * reset buf_off as this fn is called on each fork while
     134                 :            :          * restoring process tree
     135                 :            :          */
     136                 :            : 
     137                 :        483 :         buf_off = TS_BUF_OFF;
     138                 :            : 
     139         [ +  - ]:        483 :         if (!opts.log_file_per_pid) {
     140                 :        483 :                 buf_off += snprintf(buffer + buf_off, PAGE_SIZE - buf_off, "%6d: ", getpid());
     141                 :            :                 return 0;
     142                 :            :         }
     143                 :            : 
     144         [ #  # ]:          0 :         if (!opts.output)
     145                 :            :                 return 0;
     146                 :            : 
     147                 :          0 :         snprintf(path, PATH_MAX, "%s.%d", opts.output, getpid());
     148                 :            : 
     149                 :        483 :         return log_init(path);
     150                 :            : }
     151                 :            : 
     152                 :          0 : void log_fini(void)
     153                 :            : {
     154         [ #  # ]:          0 :         if (current_logfd > 2)
     155                 :          0 :                 close_safe(&current_logfd);
     156                 :            : 
     157                 :          0 :         current_logfd = DEFAULT_LOGFD;
     158                 :          0 : }
     159                 :            : 
     160                 :        349 : void log_closedir(void)
     161                 :            : {
     162                 :        349 :         close_safe(&logdir);
     163                 :        349 : }
     164                 :            : 
     165                 :        548 : void log_set_loglevel(unsigned int level)
     166                 :            : {
     167         [ +  + ]:        548 :         if (!level)
     168                 :          1 :                 current_loglevel = DEFAULT_LOGLEVEL;
     169                 :            :         else
     170                 :        547 :                 current_loglevel = level;
     171                 :        548 : }
     172                 :            : 
     173                 :        698 : unsigned int log_get_loglevel(void)
     174                 :            : {
     175                 :        698 :         return current_loglevel;
     176                 :            : }
     177                 :            : 
     178                 :     203924 : void print_on_level(unsigned int loglevel, const char *format, ...)
     179                 :            : {
     180                 :            :         va_list params;
     181                 :            :         int fd, size, ret, off;
     182                 :            : 
     183         [ +  + ]:     203924 :         if (unlikely(loglevel == LOG_MSG)) {
     184                 :          1 :                 fd = STDOUT_FILENO;
     185                 :          1 :                 off = buf_off;
     186                 :            :         } else {
     187         [ +  + ]:     203923 :                 if (loglevel > current_loglevel)
     188                 :     203924 :                         return;
     189                 :     203127 :                 fd = current_logfd;
     190                 :     203127 :                 print_ts();
     191                 :     203127 :                 off = 0;
     192                 :            :         }
     193                 :            : 
     194                 :     203128 :         va_start(params, format);
     195                 :     203128 :         size = vsnprintf(buffer + buf_off, PAGE_SIZE - buf_off, format, params);
     196                 :     203128 :         va_end(params);
     197                 :            : 
     198                 :     203128 :         size += buf_off;
     199                 :            : 
     200         [ +  + ]:     407052 :         while (off < size) {
     201                 :     203128 :                 ret = write(fd, buffer + off, size - off);
     202         [ +  - ]:     203128 :                 if (ret <= 0)
     203                 :            :                         break;
     204                 :     203128 :                 off += ret;
     205                 :            :         }
     206                 :            : }

Generated by: LCOV version 1.9