/* * Copyright (c) 2022 * by AVM GmbH Berlin, Germany * * Licence: Free, use with no restriction. * * vim: expandtab shiftwidth=4 tabstop=4 fileencoding=utf8 * * file base logging */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #if defined (HAVE_STDARG_H) && defined (__STDC__) && __STDC__ # include #else # include #endif #include #include #ifdef TIME_WITH_SYS_TIME # include # include #else # ifdef HAVE_SYS_TIME_H # include # else # include # endif #endif #include #include #include "clog2file.h" #include #include #include #define MAX_NUMBER_FILES 50 #define MAX_LOG_SIZE 20 * 1024 static char msgbuf[4096]; #define TMP128_SIZ 128 static char *clog2file_tmp128(void) { static struct tmpbuf { struct tmpbuf *next; char tmp[TMP128_SIZ]; } buffer[] = { { &buffer[1], {0} }, { &buffer[2], {0} }, { &buffer[3], {0} }, { &buffer[4], {0} }, { &buffer[5], {0} }, { &buffer[6], {0} }, { &buffer[7], {0} }, { &buffer[8], {0} }, { &buffer[9], {0} }, { &buffer[10], {0} }, { &buffer[11], {0} }, { &buffer[12], {0} }, { &buffer[13], {0} }, { &buffer[14], {0} }, { &buffer[15], {0} }, { &buffer[0], {0} }, }; static struct tmpbuf *tmp128p = &buffer[0]; char *s; tmp128p = tmp128p->next; s = tmp128p->tmp; return s; } /** * Checks if the max number of files or max total size for given path and type is reached * Deletes the oldest if needed * path and type are determined by the given dump_file_name * * @param dump_file_name filename with absolute path, path and type are extracted */ static void check_max_number_files(const char* dump_file_name) { char *path = NULL; char *pos = NULL; char *type = NULL; DIR *dirp = NULL; pos = strrchr(dump_file_name, '/'); if (pos == NULL) { return; } type = strrchr(dump_file_name, '.'); if (type == NULL) { return; } path = strndup(dump_file_name, pos - dump_file_name + 1); if (path == NULL) { return; } int file_count = 0; int dir_size = 0; dirp = opendir(path); struct dirent *entry; time_t last_modified = time(NULL); struct stat attr; char remove_file[512] = ""; //path + filename current max 29 chars if (dirp) { while ((entry = readdir(dirp)) != NULL) { if (strstr(entry->d_name, type)) { char file_complete[512] = ""; snprintf(file_complete, sizeof(file_complete), "%s%s", path, entry->d_name); if (stat(file_complete, &attr) < 0) { free(path); closedir(dirp); return; } dir_size += attr.st_size; if (last_modified > attr.st_mtime) { last_modified = attr.st_mtime; snprintf(remove_file, sizeof(remove_file), "%s", file_complete); } file_count++; } } closedir(dirp); } if (file_count > MAX_NUMBER_FILES || dir_size > MAX_LOG_SIZE) { if (!remove_file[0] == '\0') { remove(remove_file); } } free(path); } static void initlog(const char *dump_file_name) { if (!dump_file_name || dump_file_name[0] == '\0') { return; } check_max_number_files(dump_file_name); } static char* clog2file_time2isostr(time_t t) { struct tm *lt = NULL; char* s = NULL; int len = 127; s = clog2file_tmp128(); lt = localtime(&t); if (!lt) { memset(s, 0, TMP128_SIZ); return s; } snprintf(s, len, "%04d-%02d-%02d %02d:%02d:%02d", lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday, lt->tm_hour, lt->tm_min, lt->tm_sec); return s; } static void vxclog2file_msg(const char *dump_file_name, const char *prefix, const char *format, va_list args) { char *s = msgbuf; char *e = msgbuf + sizeof(msgbuf); time_t now; FILE *logfp; if (!dump_file_name || dump_file_name[0] == '\0') { return; } *s = 0; now = time(0); (void)snprintf(s, e-s, "%s ", clog2file_time2isostr(now)); s += strlen(s); if (prefix && prefix[0] != '\0') { (void)snprintf(s, e-s, "%s:", prefix); s += strlen(s); } (void)vsnprintf(s, e-s, format, args); /* K10 s += strlen(s); */ mode_t old_mask = umask(0); errno = 0; logfp = fopen(dump_file_name, "a+"); if (!logfp) { umask(old_mask); return; } fprintf(logfp, "%s\n", msgbuf); fflush(logfp); fclose(logfp); umask(old_mask); } void clog2file_vxmsg(const char *dump_file_name, const char *prefix, const char *format, va_list args) { if (!dump_file_name || dump_file_name[0] == '\0') { return; } initlog(dump_file_name); vxclog2file_msg(dump_file_name, prefix, format, args); }