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;
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);
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);
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
#if defined(__linux__)
#include <sys/syscall.h>
#endif
+#include <sys/stat.h>
#include <sys/time.h>
#include <unistd.h>
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<uint32_t>& elems);
SO_PUBLIC std::string int_vector_to_str(const std::vector<uint32_t>& 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