From 683f22482cab39728dfcec6a3df252504e914056 Mon Sep 17 00:00:00 2001 From: Philipp Kaeser Date: Wed, 30 Sep 2026 14:09:49 -0400 Subject: [PATCH 1/2] log: Updates bs_log_init_file to use base name and directory. --- include/libbase/log.h | 16 +++++++-- src/log.c | 81 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 79 insertions(+), 18 deletions(-) diff --git a/include/libbase/log.h b/include/libbase/log.h index 9493064..08173dd 100644 --- a/include/libbase/log.h +++ b/include/libbase/log.h @@ -64,9 +64,19 @@ void bs_log_vwrite(bs_log_severity_t severity, const char *fmt_ptr, va_list ap) __ARG_PRINTF__(4, 0); -/** Initialize logging system to write to |log_filename_ptr| at |severity|. */ -bool bs_log_init_file(const char *log_filename_ptr, - bs_log_severity_t severity); +/** + * Initialize logging system to write into a file pattern and directory. + * + * @param dirname_ptr Directory to log into. Uses "./" if NULL. + * @param filebase_ptr + * @param severity + * + * @return true on success. This function will fail if called more than once. + */ +bool bs_log_init_file( + const char *dirname_ptr, + const char *filebase_ptr, + bs_log_severity_t severity); /** Returns whether log outut will happen for `severity`. */ static inline bool bs_will_log(bs_log_severity_t severity) diff --git a/src/log.c b/src/log.c index b912f5d..be2d9e6 100644 --- a/src/log.c +++ b/src/log.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -41,28 +42,54 @@ bs_log_severity_t bs_log_severity = BS_WARNING; -static const char* _severity_names[5] = { +static const char *_severity_names[5] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"}; static int _log_fd = 2; +static const char *_bs_log_extension_ptr = ".log"; + static const char *_strip_prefix(const char *path_ptr); /* == Functions ============================================================ */ /* ------------------------------------------------------------------------- */ -bool bs_log_init_file(const char *log_filename_ptr, - bs_log_severity_t severity) +bool bs_log_init_file( + const char *dirname_ptr, + const char *filebase_ptr, + bs_log_severity_t severity) { - int fd = open(log_filename_ptr, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR); + static bool initialized = false; + if (initialized) return false; + + if (NULL == dirname_ptr) dirname_ptr = "./"; + + // Attempt to create the directory, unless it exists. + if (!bs_file_realpath_is(dirname_ptr, S_IFDIR) && + !bs_file_mkdir_p(dirname_ptr, 0700)) return false; + + // Construct the log file's name. + char path[PATH_MAX + 1]; + int len = snprintf(path, PATH_MAX + 1, "%s/%s%s", + dirname_ptr, filebase_ptr, _bs_log_extension_ptr); + if (PATH_MAX <= len) { + bs_log(BS_ERROR, "Failed snprintf(%p, %d, \"%s/%s%s\"): %d", + path, PATH_MAX + 1, dirname_ptr, filebase_ptr, + _bs_log_extension_ptr, len); + return false; + } + + // Now, actually create it. + int fd = open(path, O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR); if (0 > fd) { bs_log(BS_ERROR | BS_ERRNO, "Failed open(%s, O_CREATE | O_WRONLY, S_IWUSR | S_IRUSR)", - log_filename_ptr); + path); return false; } _log_fd = fd; bs_log_severity = severity; + initialized = true; return true; } @@ -160,6 +187,21 @@ const char *_strip_prefix(const char *path_ptr) /* == Test functions ======================================================= */ +static void test_file(bs_test_t *test_ptr); +static void test_strip_prefix(bs_test_t *test_ptr); +static void test_log(bs_test_t *test_ptr); + +/** Unit test cases. */ +static const bs_test_case_t bs_log_test_cases[] = { + { true, "file", test_file }, + { true, "basename", test_strip_prefix }, + { true, "log", test_log }, + BS_TEST_CASE_SENTINEL(), +}; + +const bs_test_set_t bs_log_test_set = BS_TEST_SET( + true, "log", bs_log_test_cases); + /* ------------------------------------------------------------------------- */ /** * Helper method: Test that |expected_str| can be read from the descriptor @@ -222,18 +264,26 @@ void verify_log_output_equals_at( } } -static void test_strip_prefix(bs_test_t *test_ptr); -static void test_log(bs_test_t *test_ptr); +/* ------------------------------------------------------------------------- */ +/** Verifies that a log file is created in the given directory. */ +void test_file(bs_test_t *test_ptr) +{ + BS_TEST_VERIFY_TRUE( + test_ptr, + bs_log_init_file(bs_test_temp_path(test_ptr, "sub"), "base", BS_INFO)); -/** Unit test cases. */ -static const bs_test_case_t bs_log_test_cases[] = { - { true, "basename", test_strip_prefix }, - { true, "log", test_log }, - BS_TEST_CASE_SENTINEL(), -}; + const char *log_name_ptr = bs_test_temp_path(test_ptr, "sub/base.log"); + BS_TEST_VERIFY_TRUE(test_ptr, bs_file_realpath_is(log_name_ptr, S_IFREG)); -const bs_test_set_t bs_log_test_set = BS_TEST_SET( - true, "log", bs_log_test_cases); + BS_TEST_VERIFY_EQ(test_ptr, 0, unlink(log_name_ptr)); + BS_TEST_VERIFY_EQ( + test_ptr, 0, rmdir(bs_test_temp_path(test_ptr, "sub"))); + + // Must fail on further initialization attempt(s). + BS_TEST_VERIFY_FALSE( + test_ptr, + bs_log_init_file(bs_test_temp_path(test_ptr, "sub"), "other", BS_INFO)); +} /* ------------------------------------------------------------------------- */ void test_strip_prefix(bs_test_t *test_ptr) @@ -254,6 +304,7 @@ void test_log(bs_test_t *test_ptr) bs_log_severity_t backup_severity; backup_severity = bs_log_severity; + bs_log_severity = BS_WARNING; int fds[2]; if (0 != pipe(fds)) { From efc09248b89a16f92556be1280418babf9217a8c Mon Sep 17 00:00:00 2001 From: Philipp Kaeser Date: Wed, 30 Sep 2026 15:06:26 -0400 Subject: [PATCH 2/2] log: Clamps severity to the valid values. --- src/log.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/log.c b/src/log.c index be2d9e6..a54e195 100644 --- a/src/log.c +++ b/src/log.c @@ -115,6 +115,7 @@ void bs_log_vwrite(bs_log_severity_t severity, char buf[BS_LOG_MAX_BUF_SIZE + 1]; size_t pos = 0; + if ((severity & 0x7f) > BS_FATAL) severity = BS_FATAL | (severity & 0x80); const char *color_attr_ptr = ""; switch (severity & 0x7f) { case BS_DEBUG: color_attr_ptr = "\e[90m"; break; // Dark gray foreground.