Log file (log::destination::file) now creates directory structure if needed.

You could already have something like:
log { source { !debug; all; } destination { file "ircd.%Y-%m-%d.log"; } }
But now you can also have:
log { source { !debug; all; } destination { file "%Y-%m-%d/ircd.log"; } }

This is especially useful if you output to multiple log files and then
want them grouped by date in a directory.
This commit is contained in:
Bram Matthys 2022-08-05 10:56:00 +02:00
parent 0e6fc07bd9
commit 55c52c3693
No known key found for this signature in database
GPG key ID: BF8116B163EAAE98
3 changed files with 79 additions and 9 deletions

View file

@ -669,6 +669,9 @@ extern char *unreal_mktemp(const char *dir, const char *suffix);
extern char *unreal_getpathname(const char *filepath, char *path);
extern const char *unreal_getfilename(const char *path);
extern const char *unreal_getmodfilename(const char *path);
extern int unreal_create_directory_structure_for_file(const char *fname, mode_t mode);
extern int unreal_create_directory_structure(const char *dname, mode_t mode);
extern int unreal_mkdir(const char *pathname, mode_t mode);
extern int unreal_copyfile(const char *src, const char *dest);
extern int unreal_copyfileex(const char *src, const char *dest, int tryhardlink);
extern time_t unreal_getfilemodtime(const char *filename);

View file

@ -986,17 +986,27 @@ void do_unreal_log_disk(LogLevel loglevel, const char *subsystem, const char *ev
l->logfd = fd_fileopen(l->file, O_CREAT|O_APPEND|O_WRONLY);
if (l->logfd == -1)
{
if (!loop.booted)
if (errno == ENOENT)
{
config_status("WARNING: Unable to write to '%s': %s", l->file, strerror(errno));
} else {
if (last_log_file_warning + 300 < TStime())
{
config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", l->file, strerror(errno));
last_log_file_warning = TStime();
}
/* Create directory structure and retry */
unreal_create_directory_structure_for_file(l->file, 0777);
l->logfd = fd_fileopen(l->file, O_CREAT|O_APPEND|O_WRONLY);
}
if (l->logfd == -1)
{
/* Still failed! */
if (!loop.booted)
{
config_status("WARNING: Unable to write to '%s': %s", l->file, strerror(errno));
} else {
if (last_log_file_warning + 300 < TStime())
{
config_status("WARNING: Unable to write to '%s': %s. This warning will not re-appear for at least 5 minutes.", l->file, strerror(errno));
last_log_file_warning = TStime();
}
}
continue;
}
continue;
}
}

View file

@ -856,6 +856,63 @@ const char *unreal_getfilename(const char *path)
return end;
}
/** Wrapper for mkdir() so you don't need ifdefs everywhere for Windows.
* @returns 0 on failure!! (like mkdir)
*/
int unreal_mkdir(const char *pathname, mode_t mode)
{
#ifdef _WIN32
return mkdir(pathname);
#else
return mkdir(pathname, mode);
#endif
}
/** Create the entire directory structure.
* @param dname The directory name, eg /home/irc/unrealircd/logs/2022/08/05
* @param mode The mode to create with, eg 0777. Ignored on Windows.
* @returns 1 on success, 0 on failure.
*/
int unreal_create_directory_structure(const char *dname, mode_t mode)
{
if (unreal_mkdir(dname, mode) == 0)
{
/* Ok, that failed as well, we have some work to do:
* for every path element run mkdir().
*/
int lastresult;
char buf[512], *p;
strlcpy(buf, dname, sizeof(buf)); /* work on a copy */
for (p=strchr(buf+1, '/'); p; p=strchr(p+1, '/'))
{
*p = '\0';
unreal_mkdir(buf,mode);
*p = '/';
}
/* Finally, try the complete path */
if (unreal_mkdir(dname, mode))
return 0; /* failed */
/* fallthrough.... */
}
return 1; /* success */
}
/** Create entire directory structure for a path with a filename.
* @param fname The full path name, eg /home/irc/unrealircd/logs/2022/08/05/ircd.log
* @param mode The mode to create with, eg 0777. Ignored on Windows.
* @notes This is used as an easier way to call unreal_create_directory_structure()
* if you have a filename instead of the directory part.
* @returns 1 on success, 0 on failure.
*/
int unreal_create_directory_structure_for_file(const char *fname, mode_t mode)
{
char buf[PATH_MAX+1];
const char *path = unreal_getpathname(fname, buf);
if (!path)
return 0;
return unreal_create_directory_structure(path, mode);
}
/** Returns the special module tmp name for a given path.
* The original string is not modified.
*/