From: Serhii Vlasiuk -X (svlasiuk - SOFTSERVE INC at Cisco) Date: Thu, 25 Apr 2024 07:52:50 +0000 (+0000) Subject: Pull request #4262: utils: move file specific functions from perfmonitor to utils X-Git-Tag: 3.2.1.0~19 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a282e6b9e861ad935ab5965c5661d72ca3e2ba54;p=thirdparty%2Fsnort3.git Pull request #4262: utils: move file specific functions from perfmonitor to utils Merge in SNORT/snort3 from ~SVLASIUK/snort3:fw_hitcount_stats to master Squashed commit of the following: commit 14d0ceb64c2ded61923eeb35be829db4f0e1b906 Author: Serhii Vlasiuk Date: Fri Mar 22 13:39:45 2024 +0200 utils: move file specific functions from perfmonitor to utils --- diff --git a/src/network_inspectors/perf_monitor/perf_tracker.cc b/src/network_inspectors/perf_monitor/perf_tracker.cc index 0d96c42db..0c7cda2f8 100644 --- a/src/network_inspectors/perf_monitor/perf_tracker.cc +++ b/src/network_inspectors/perf_monitor/perf_tracker.cc @@ -40,22 +40,6 @@ using namespace snort; using namespace std; -static inline bool check_file_size(FILE* fh, uint64_t max_file_size) -{ - int fd; - struct stat fstats; - - if (!fh) - return false; - - fd = fileno(fh); - if ((fstat(fd, &fstats) == 0) - && ((uint64_t)fstats.st_size >= max_file_size)) - return true; - - return false; -} - PerfTracker::PerfTracker(PerfConfig* config, const char* tracker_name) { max_file_size = config->max_file_size; @@ -165,190 +149,11 @@ bool PerfTracker::open(bool append) return true; } -// FIXIT-M combine with fileRotate -// FIXIT-M refactor file naming foo to use std::string -static bool rotate_file(const char* old_file, FILE* old_fh, - uint32_t max_file_size) -{ - time_t ts; - char rotate_file[PATH_MAX]; - struct stat fstats; - - if (!old_file) - return false; - - if (!old_fh) - { - ErrorMessage("Perfmonitor: Performance stats file \"%s\" " - "isn't open.\n", old_file); - return false; - } - - // Close the current stats file if it's already open - fclose(old_fh); - old_fh = nullptr; - - // FIXIT-M does this make sense? or should it be the first timestamp in the file? - // Rename current stats file with yesterday's date - // Get current time, then subtract one day to get yesterday - ts = time(nullptr); - ts -= (24*60*60); - - // Create rotate file name based on path, optional prefix and date - // Need to be mindful that we get 64-bit times on OSX - SnortSnprintf(rotate_file, PATH_MAX, "%s_" STDu64, old_file, (uint64_t)ts); - - // If the rotate file doesn't exist, just rename the old one to the new one - if (stat(rotate_file, &fstats) != 0) - { - if (rename(old_file, rotate_file) != 0) - { - ErrorMessage("Perfmonitor: Could not rename performance stats " - "file from \"%s\" to \"%s\": %s.\n", - old_file, rotate_file, get_error(errno)); - } - } - else // Otherwise, if it does exist, append data from current stats file to it - { - char read_buf[4096]; - size_t num_read, num_wrote; - FILE* rotate_fh; - int rotate_index = 0; - char rotate_file_with_index[PATH_MAX]; - - // This file needs to be readable by everyone - mode_t old_umask = umask(022); - - do - { - do - { - rotate_index++; - - // Check to see if there are any files already rotated and indexed - SnortSnprintf(rotate_file_with_index, PATH_MAX, "%s.%02d", - rotate_file, rotate_index); - } - while (stat(rotate_file_with_index, &fstats) == 0); - - // Subtract one to append to last existing file - rotate_index--; - - if (rotate_index == 0) - { - rotate_file_with_index[0] = 0; - rotate_fh = fopen(rotate_file, "a"); - } - else - { - SnortSnprintf(rotate_file_with_index, PATH_MAX, "%s.%02d", - rotate_file, rotate_index); - rotate_fh = fopen(rotate_file_with_index, "a"); - } - - if (!rotate_fh) - { - ErrorMessage("Perfmonitor: Could not open performance stats " - "archive file \"%s\" for appending: %s.\n", - *rotate_file_with_index ? rotate_file_with_index : rotate_file, - get_error(errno)); - break; - } - - old_fh = fopen(old_file, "r"); - if (!old_fh) - { - ErrorMessage("Perfmonitor: Could not open performance stats file " - "\"%s\" for reading to copy to archive \"%s\": %s.\n", - old_file, (*rotate_file_with_index ? rotate_file_with_index : - rotate_file), get_error(errno)); - break; - } - - while (!feof(old_fh)) - { - // This includes the newline from the file. - if (!fgets(read_buf, sizeof(read_buf), old_fh)) - { - if (feof(old_fh)) - break; - - if (ferror(old_fh)) - { - // A read error occurred - ErrorMessage("Perfmonitor: Error reading performance stats " - "file \"%s\": %s.\n", old_file, get_error(errno)); - break; - } - } - - num_read = strlen(read_buf); - - if (num_read > 0) - { - int rotate_fd = fileno(rotate_fh); - - if (fstat(rotate_fd, &fstats) != 0) - { - ErrorMessage("Perfmonitor: Error getting file " - "information for \"%s\": %s.\n", - *rotate_file_with_index ? rotate_file_with_index : rotate_file, - get_error(errno)); - break; - } - - if (((uint32_t)fstats.st_size + num_read) > max_file_size) - { - fclose(rotate_fh); - - rotate_index++; - - // Create new file same as before but with an index added to the end - SnortSnprintf(rotate_file_with_index, PATH_MAX, "%s.%02d", - rotate_file, rotate_index); - - rotate_fh = fopen(rotate_file_with_index, "a"); - if (!rotate_fh) - { - ErrorMessage("Perfmonitor: Could not open performance " - "stats archive file \"%s\" for writing: %s.\n", - rotate_file_with_index, get_error(errno)); - break; - } - } - - num_wrote = fprintf(rotate_fh, "%s", read_buf); - if ((num_wrote != num_read) && ferror(rotate_fh)) - { - // A bad write occurred - ErrorMessage("Perfmonitor: Error writing to performance " - "stats archive file \"%s\": %s.\n", rotate_file, get_error(errno)); - break; - } - - fflush(rotate_fh); - } - } - } - while (false); - - if (rotate_fh) - fclose(rotate_fh); - - if (old_fh) - fclose(old_fh); - - umask(old_umask); - } - - return true; -} - bool PerfTracker::rotate() { if (fh && fh != stdout) { - if (!rotate_file(fname.c_str(), fh, max_file_size)) + if (!rotate_file_for_max_size("Perfmonitor", fname.c_str(), fh, max_file_size)) return false; return open(false); diff --git a/src/profiler/profiler_nodes.cc b/src/profiler/profiler_nodes.cc index 7933abc2a..d45363705 100644 --- a/src/profiler/profiler_nodes.cc +++ b/src/profiler/profiler_nodes.cc @@ -486,24 +486,6 @@ bool ProfilerNodeMap::rotate(std::string& fname, uint64_t max_file_size) return false; } -static inline bool check_file_size(FILE* fh, uint64_t max_file_size) -{ - int fd; - struct stat fstats; - - if (!fh) - return false; - - fd = fileno(fh); - if ((fstat(fd, &fstats) == 0) - and ((uint64_t)fstats.st_size >= max_file_size)) - { - return true; - } - - return false; -} - inline void ProfilerNodeMap::create_new_file(std::string& fname, uint64_t max_file_size) { open(fname, max_file_size, true); diff --git a/src/utils/util.cc b/src/utils/util.cc index 868b4ffcc..7b8610def 100644 --- a/src/utils/util.cc +++ b/src/utils/util.cc @@ -687,6 +687,198 @@ std::string int_vector_to_str(const std::vector& elems, char delim) return str; } +bool check_file_size(FILE* fh, uint64_t max_file_size) +{ + int fd; + struct stat fstats; + + if (!fh) + return false; + + fd = fileno(fh); + if ((fstat(fd, &fstats) == 0) + && ((uint64_t)fstats.st_size >= max_file_size)) + return true; + + return false; +} + +bool rotate_file_for_max_size(const char* file_owner, const char* old_file, + FILE* old_fh, uint32_t max_file_size) +{ + time_t ts; + char rotate_file[PATH_MAX]; + struct stat fstats; + + if (!old_file) + return false; + + if (!old_fh) + { + ErrorMessage("%s: file \"%s\" isn't open.\n", file_owner, old_file); + return false; + } + + // Close the current stats file if it's already open + fclose(old_fh); + old_fh = nullptr; + + // FIXIT-M does this make sense? or should it be the first timestamp in the file? + // Rename current stats file with yesterday's date + // Get current time, then subtract one day to get yesterday + ts = time(nullptr); + ts -= (24*60*60); + + // Create rotate file name based on path, optional prefix and date + // Need to be mindful that we get 64-bit times on OSX + SnortSnprintf(rotate_file, PATH_MAX, "%s_" STDu64, old_file, (uint64_t)ts); + + // If the rotate file doesn't exist, just rename the old one to the new one + if (stat(rotate_file, &fstats) != 0) + { + if (rename(old_file, rotate_file) != 0) + { + ErrorMessage("%s: Could not rename " + "file from \"%s\" to \"%s\": %s.\n", + file_owner, old_file, rotate_file, get_error(errno)); + } + } + else // Otherwise, if it does exist, append data from current stats file to it + { + char read_buf[4096]; + size_t num_read, num_wrote; + FILE* rotate_fh; + int rotate_index = 0; + char rotate_file_with_index[PATH_MAX]; + + // This file needs to be readable by everyone + mode_t old_umask = umask(022); + + do + { + do + { + rotate_index++; + + // Check to see if there are any files already rotated and indexed + SnortSnprintf(rotate_file_with_index, PATH_MAX, "%s.%02d", + rotate_file, rotate_index); + } + while (stat(rotate_file_with_index, &fstats) == 0); + + // Subtract one to append to last existing file + rotate_index--; + + if (rotate_index == 0) + { + rotate_file_with_index[0] = 0; + rotate_fh = fopen(rotate_file, "a"); + } + else + { + SnortSnprintf(rotate_file_with_index, PATH_MAX, "%s.%02d", + rotate_file, rotate_index); + rotate_fh = fopen(rotate_file_with_index, "a"); + } + + if (!rotate_fh) + { + ErrorMessage("%s: Could not open " + "archive file \"%s\" for appending: %s.\n", + file_owner, *rotate_file_with_index ? rotate_file_with_index : rotate_file, + get_error(errno)); + break; + } + + old_fh = fopen(old_file, "r"); + if (!old_fh) + { + ErrorMessage("%s: Could not open file " + "\"%s\" for reading to copy to archive \"%s\": %s.\n", + file_owner, old_file, (*rotate_file_with_index ? rotate_file_with_index : + rotate_file), get_error(errno)); + break; + } + + while (!feof(old_fh)) + { + // This includes the newline from the file. + if (!fgets(read_buf, sizeof(read_buf), old_fh)) + { + if (feof(old_fh)) + break; + + if (ferror(old_fh)) + { + // A read error occurred + ErrorMessage("%s: Error reading " + "file \"%s\": %s.\n", file_owner, old_file, get_error(errno)); + break; + } + } + + num_read = strlen(read_buf); + + if (num_read > 0) + { + int rotate_fd = fileno(rotate_fh); + + if (fstat(rotate_fd, &fstats) != 0) + { + ErrorMessage("%s: Error getting file " + "information for \"%s\": %s.\n", + file_owner, *rotate_file_with_index ? rotate_file_with_index : rotate_file, + get_error(errno)); + break; + } + + if (((uint32_t)fstats.st_size + num_read) > max_file_size) + { + fclose(rotate_fh); + + rotate_index++; + + // Create new file same as before but with an index added to the end + SnortSnprintf(rotate_file_with_index, PATH_MAX, "%s.%02d", + rotate_file, rotate_index); + + rotate_fh = fopen(rotate_file_with_index, "a"); + if (!rotate_fh) + { + ErrorMessage("%s: Could not open " + "stats archive file \"%s\" for writing: %s.\n", + file_owner, rotate_file_with_index, get_error(errno)); + break; + } + } + + num_wrote = fprintf(rotate_fh, "%s", read_buf); + if ((num_wrote != num_read) && ferror(rotate_fh)) + { + // A bad write occurred + ErrorMessage("%s: Error writing to " + "stats archive file \"%s\": %s.\n", file_owner, rotate_file, get_error(errno)); + break; + } + + fflush(rotate_fh); + } + } + } + while (false); + + if (rotate_fh) + fclose(rotate_fh); + + if (old_fh) + fclose(old_fh); + + umask(old_umask); + } + + return true; +} + } #ifdef UNIT_TEST diff --git a/src/utils/util.h b/src/utils/util.h index 6625a21f6..4926790be 100644 --- a/src/utils/util.h +++ b/src/utils/util.h @@ -27,6 +27,7 @@ #if defined(__linux__) #include #endif +#include #include #include @@ -132,6 +133,9 @@ SO_PUBLIC void ts_print(const struct timeval*, char*, bool yyyymmdd = false); void uint8_to_printable_str(const uint8_t* buff, unsigned len, std::string& print_str); SO_PUBLIC void str_to_int_vector(const std::string& s, char delim, std::vector& elems); SO_PUBLIC std::string int_vector_to_str(const std::vector& elems, char delim = ','); +SO_PUBLIC bool rotate_file_for_max_size(const char* file_owner, const char* old_file, + FILE* old_fh, uint32_t max_file_size); +SO_PUBLIC bool check_file_size(FILE* fh, uint64_t max_file_size); } #endif