Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup old log files #2501

Merged
merged 1 commit into from
Dec 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions lib/framework/physfs_ext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ bool WZ_PHYSFS_createPlatformPrefDir(const WzString& basePath, const WzString& a
return true;
}

static bool filenameEndWithExtension(const char *filename, const char *extension)
bool filenameEndWithExtension(const char *filename, const char *extension)
{
if (nullptr == filename)
{
Expand All @@ -146,18 +146,26 @@ struct compareTimes {

int WZ_PHYSFS_cleanupOldFilesInFolder(const char *path, const char *extension, int fileLimit, const std::function<bool (const char *fileName)>& deleteFileFunction)
{
ASSERT_OR_RETURN(-1, path != nullptr, "Null path");
ASSERT_OR_RETURN(-1, extension != nullptr, "Null extension");
CleanupFileEnumFilterFunctions filterFuncs;
filterFuncs.fileNameFilterFunction = [extension](const char *fileName) -> bool {
return filenameEndWithExtension(fileName, extension);
};
return WZ_PHYSFS_cleanupOldFilesInFolder(path, filterFuncs, fileLimit, deleteFileFunction);
}

int WZ_PHYSFS_cleanupOldFilesInFolder(const char *path, const CleanupFileEnumFilterFunctions& fileFilterFunctions, int fileLimit, const std::function<bool (const char *fileName)>& deleteFileFunction)
{
ASSERT_OR_RETURN(-1, path != nullptr, "Null path");
ASSERT_OR_RETURN(-1, deleteFileFunction != nullptr, "No deleteFileFunction");
char **i, **files;
files = PHYSFS_enumerateFiles(path);
ASSERT_OR_RETURN(-1, files, "PHYSFS_enumerateFiles(\"%s\") failed: %s", path, WZ_PHYSFS_getLastError());
int nfiles = 0;
for (i = files; *i != nullptr; ++i)
{
if (!filenameEndWithExtension(*i, extension))
if (fileFilterFunctions.fileNameFilterFunction != nullptr && !fileFilterFunctions.fileNameFilterFunction(*i))
{
// If it doesn't, move on to the next filename
continue;
}
nfiles++;
Expand All @@ -169,21 +177,24 @@ int WZ_PHYSFS_cleanupOldFilesInFolder(const char *path, const char *extension, i
}

// too many files
debug(LOG_SAVE, "found %i files with ext %s, limit is %i", nfiles, extension, fileLimit);
debug(LOG_SAVE, "found %i matching files in %s, limit is %i", nfiles, path, fileLimit);

// build a sorted list of file + save time
std::multiset<SaveTimePair, compareTimes> fileTimes;
char savefile[PATH_MAX];
for (i = files; *i != nullptr; ++i)
{
if (!filenameEndWithExtension(*i, extension))
if (fileFilterFunctions.fileNameFilterFunction != nullptr && !fileFilterFunctions.fileNameFilterFunction(*i))
{
// If it doesn't, move on to the next filename
continue;
}
/* Gather save-time */
snprintf(savefile, sizeof(savefile), "%s/%s", path, *i);
time_t savetime = WZ_PHYSFS_getLastModTime(savefile);
if (fileFilterFunctions.fileLastModifiedFilterFunction != nullptr && !fileFilterFunctions.fileLastModifiedFilterFunction(savetime))
{
continue;
}
fileTimes.insert(SaveTimePair{*i, savetime});
}

Expand Down
11 changes: 11 additions & 0 deletions lib/framework/physfs_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,15 @@ bool WZ_PHYSFS_createPlatformPrefDir(const WzString& basePath, const WzString& a
// fileLimit: < 0, pass the single oldest matching file to deleteFileFunction
int WZ_PHYSFS_cleanupOldFilesInFolder(const char *path, const char *extension, int fileLimit, const std::function<bool (const char *fileName)>& deleteFileFunction);

struct CleanupFileEnumFilterFunctions
{
// Return `true` to include a file, `false` to exclude it
std::function<bool (const char *fileName)> fileNameFilterFunction;
std::function<bool (time_t fileLastModified)> fileLastModifiedFilterFunction;
};

int WZ_PHYSFS_cleanupOldFilesInFolder(const char *path, const CleanupFileEnumFilterFunctions& fileFilterFunctions, int fileLimit, const std::function<bool (const char *fileName)>& deleteFileFunction);

bool filenameEndWithExtension(const char *filename, const char *extension);

#endif // _physfs_ext_h
38 changes: 38 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1581,6 +1581,43 @@ static void wzCmdInterfaceShutdown()
stdInThreadShutdown();
}

static void cleanupOldLogFiles()
{
constexpr int MAX_OLD_LOGS = 50;
ASSERT_OR_RETURN(, PHYSFS_isInit() != 0, "PhysFS isn't initialized");
// safety check to ensure we *never* delete the current log file
WzString fullCurrentLogFileName = WzString::fromUtf8(getDefaultLogFilePath("/"));
if (fullCurrentLogFileName.startsWith("logs/"))
{
fullCurrentLogFileName.remove(0, 5);
}

CleanupFileEnumFilterFunctions filterFuncs;
constexpr std::chrono::hours MinDeletableAge(24 * 7); // never delete logs that are less than a week old
auto currentTime = std::chrono::system_clock::now();
filterFuncs.fileNameFilterFunction = [](const char *fileName) -> bool {
return filenameEndWithExtension(fileName, ".txt") || filenameEndWithExtension(fileName, ".log");
};
filterFuncs.fileLastModifiedFilterFunction = [currentTime, MinDeletableAge](time_t fileLastModified) -> bool {
return std::chrono::duration_cast<std::chrono::hours>(currentTime - std::chrono::system_clock::from_time_t(fileLastModified)) >= MinDeletableAge;
};

// clean up old log .txt / .log files
WZ_PHYSFS_cleanupOldFilesInFolder("logs", filterFuncs, MAX_OLD_LOGS, [fullCurrentLogFileName](const char *fileName){
if (fullCurrentLogFileName.compare(fileName) == 0)
{
// skip
return true;
}
if (PHYSFS_delete(fileName) == 0)
{
debug(LOG_ERROR, "Failed to delete old log file: %s", fileName);
return false;
}
return true;
});
}

// for backend detection
extern const char *BACKEND;

Expand Down Expand Up @@ -1985,6 +2022,7 @@ int realmain(int argc, char *argv[])
#endif
wzCmdInterfaceShutdown();
urlRequestShutdown();
cleanupOldLogFiles();
systemShutdown();
#ifdef WZ_OS_WIN // clean up the memory allocated for the command line conversion
for (int i = 0; i < argc; i++)
Expand Down