bbclog.c 5.23 KB
#include <stdarg.h>
#include <errno.h>
#include <string.h>

#include "bbclocal.h"

int bbc_diag_mode = 1;
int bbc_diag_level = MSG_INFO;

#if BBC_DEBUG
int bbc_log_level = MSG_DEBUG;
#else
int bbc_log_level = MSG_INFO;
#endif

const char* bbc_log_file  = NULL; /*"bbc.log"; */
int bbc_log_timestamp = 1;
int bbc_log_initialized = 0;

static const char* bbc_errlevels[] =
{
    "EMERG ",
    "ALERT ",
    "CRIT  ",
    "ERROR ",
    "WARN  ",
    "NOTICE",
    "INFO  ",
    "DEBUG ",
    "ALL   "
};

static const char* bbc_errstrs[] = 
{
    "BBC_OK (No error)",
    "BBC_NOFORMAT (Card has errors and requires reformat)",
    "BBC_NOID (BBID is not present on card)",
    "BBC_NOSPACE (No space left on card)",
    "BBC_NOCARD (Card has been removed)",
    "BBC_CARDCHANGE (Card has changed, BBCInit() need to be called)",
    "BBC_TOOMANY (Too many active handles)",
    "BBC_BADHANDLE (Invalid handle)",
    "BBC_BADLENGTH (Invalid object length)",
    "BBC_CARDFAILED (Card has too many bad blks or is unusable)",
    "BBC_ERROR (Generic error)",
    "BBC_EIO (IO error)",
    "BBC_DATAERR (block read with DB ecc error)",
    "BBC_NODEV (device not connected)",
    "BBC_NOFILE (file does not exist on Card)",
    "BBC_BADBLK (block marked bad)",
    "BBC_SA1DIFFERS (BBCVerifySKSA2 finds SA1 different)",
    "BBC_MULTIPLE_BB (BBCInit() found multiple BB connection)",
    "BBC_MULTIPLE_FILE (cid mapped to both .app and .rec files)",
    "BBC_SYNCLOST (Protocol synchronization lost)",
    "BBC_NOMEM (Unable to allocate memory)",
    "BBC_BADARG (Invalid argument)",
    "BBC_DEVBUSY (Device already opened)",
    "BBC_DEVERR (Device error)",
    "BBC_TIMEOUT (Timeout)"
};

int BBCSetLogLevel(int level) {
    bbc_log_level = level;
    bbc_log_initialized = 1;
    return BBC_OK;
}

int BBCSetLogFile(const char* filename) {
    bbc_log_file = filename;
    bbc_log_initialized = 1;
    return BBC_OK;
}

int BBCSetDiagMode(int mode) {
    bbc_diag_mode = mode;
    return BBC_OK;
}

const char* bbc_errorstr(int rv)
{
    int index = -rv;
    if ((index < 0) || (index >= sizeof(bbc_errstrs)/sizeof(bbc_errstrs[0])))
        return "Unknown error";
    else return bbc_errstrs[index];
}

const char* bbc_errorlevel(int level)
{
    int index = level;
    if ((index < 0) || (index >= sizeof(bbc_errlevels)/sizeof(bbc_errlevels[0])))
        return "      ";
    else return bbc_errlevels[index];
}

void bbc_init_log()
{
    char* log_level;

    if ((log_level = getenv("BBC_LOG_LEVEL")) != NULL) {
        bbc_log_level = atoi(log_level);
    }
    bbc_log_file = getenv("BBC_LOG_FILE");

    bbc_log_initialized = 1;
}

void bbclog(int level, const char *fmt, ...)
{
    va_list ap;
    FILE* log_fp = stderr;
    int file = 0;

    if (!bbc_log_initialized) bbc_init_log();

    if (level <= bbc_log_level) {
        time_t t = time(NULL);
        char* timebuf = ctime(&t); 
        int timelen = strlen(timebuf);
        if ((timelen > 0) && (timebuf[timelen-1] == '\n'))
            timebuf[timelen-1] = '\0';

        if (bbc_log_file) {
            log_fp = fopen(bbc_log_file, "a");
            if (log_fp == NULL) {
                log_fp = stderr;
            }
            else {
                file = 1;
            }
        }

        if (bbc_log_timestamp) {
            fprintf(log_fp,"%s %s ", timebuf, bbc_errorlevel(level));
        }
        else {
            fprintf(log_fp,"%s ", bbc_errorlevel(level));
        }
        va_start (ap, fmt);
        vfprintf (log_fp, fmt, ap);
        va_end (ap);

        if (file) {
            fclose(log_fp);
        }
        else {
            fflush (stderr);
        }
    }
} 

void bbclog_bbcerror(const char* msg, int rv)
{
    const char* error_msg = bbc_errorstr(rv);
    BBC_LOG(MSG_ERR, "%s %d: %s\n", msg, rv, error_msg);
}

/* Logs a system error */
#ifdef WIN32
/* Version for window routines that needs to use GetLastError() */
void _bbclog_syserror(int level, const char* msg, DWORD error_code) 
{
    LPVOID lpMsgBuf;
    if (FormatMessage( 
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM | 
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        error_code,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
        (LPTSTR) &lpMsgBuf,
        0,
        NULL )) 
    {
        BBC_LOG(level, "%s: %s\n", msg, lpMsgBuf);
        LocalFree(lpMsgBuf);
    }
    else BBC_LOG(level, "%s: Error %d\n", msg, error_code);
}

void bbclog_syserror(const char* msg) 
{
    DWORD  error_code = GetLastError();
    _bbclog_syserror(MSG_ERR, msg, error_code);
}

#else /* Normal system calls */
void bbclog_syserror(const char* msg)
{
    char* error_msg = strerror(errno);
    BBC_LOG(MSG_ERR, "%s: %s\n", msg, error_msg);
}
#endif

void bbclog_perror(const char* msg)
{
    char* error_msg = strerror(errno);
    BBC_LOG(MSG_ERR, "%s: %s\n", msg, error_msg);
}


#ifdef WIN32
int __bbcdiag_deltat(struct _timeb t1, struct _timeb t2)
{
    return (t2.time - t1.time)*1000 + (t2.millitm - t1.millitm);
}
#else
int __bbcdiag_deltat(struct timeval tv1, struct timeval tv2)
{
    return (tv2.tv_sec-tv1.tv_sec)*1000 + (tv2.tv_usec-tv1.tv_usec)/1000;
}
#endif

float __bbcdiag_getKBs(int bytes, int ms)
{
    if (ms == 0) ms = 1;  // Make sure we are dividing by 1 msec at least
    return bytes/1024.f/(ms/1000.f);
}