aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichał Łyszczek <michal.lyszczek@bofc.pl>2018-04-22 17:07:09 +0200
committerMichał Łyszczek <michal.lyszczek@bofc.pl>2018-04-22 17:07:09 +0200
commita31fa3a531d338997dece723697f23940f8d0d8b (patch)
tree5de34774986ccabb353df1a26090cfe01cba9a36
parentd310bfd17fb51699086f47fa0a3e57878c0a8c83 (diff)
downloadembedlog-a31fa3a531d338997dece723697f23940f8d0d8b.tar.gz
embedlog-a31fa3a531d338997dece723697f23940f8d0d8b.tar.bz2
embedlog-a31fa3a531d338997dece723697f23940f8d0d8b.zip
support automatic reopening of files when frotate is enabled
-rw-r--r--src/el-file.c61
-rw-r--r--tst/test-el-file.c345
2 files changed, 347 insertions, 59 deletions
diff --git a/src/el-file.c b/src/el-file.c
index 0b6512c..cafa331 100644
--- a/src/el-file.c
+++ b/src/el-file.c
@@ -284,6 +284,7 @@ skip_rotate:
return 0;
}
+
/* ==========================================================================
__ __ _
____ __ __ / /_ / /(_)_____
@@ -540,6 +541,7 @@ int el_file_open
return -1;
}
+ fseek(options->file, 0, SEEK_END);
options->fpos = ftell(options->file);
return 0;
}
@@ -565,6 +567,19 @@ int el_file_putb
VALID(EBADF, options->current_log[0] != '\0');
+ /*
+ * we need to reopen our file if it wasn't opened yet, or was removed
+ * due to error or deliberate acion of user
+ */
+
+ if (el_file_exists(options->current_log) == 0 || options->file == NULL)
+ {
+ if (el_file_open(options) != 0)
+ {
+ return -1;
+ }
+ }
+
if (options->frotate_number)
{
if (options->fpos != 0 && options->fpos + mlen > options->frotate_size)
@@ -595,49 +610,6 @@ int el_file_putb
}
}
- if (el_file_exists(options->current_log) == 0)
- {
- /*
- * file doesn't exist, it may happen when someone unlinks currently
- * opened file. Even tough user unlinked our log file, we still have
- * file opened, so this file exists in the system, but not in the
- * file system tree and as such, every write to such file is
- * effectively writing to /dev/null. To prevent that, we close and
- * reopen our current log file
- */
-
- if (options->file)
- {
- fclose(options->file);
- }
-
- if ((options->file = fopen(options->current_log, "a")) == NULL)
- {
- return -1;
- }
-
- options->fpos = 0;
- }
-
- /*
- * there is situation where we options->file is NULL here, it's when
- * logs are on externally (like SD card) mounted directory, and this
- * directory gets unmounted (or whatever, it dissapear), when we try to
- * write to such directory we will fail and options->current_log will be
- * set to NULL. Now when that directory reappear with previous content,
- * we skip el_file_exists check (because file does exist) and we land
- * here with NULL stream which on some systems may result in segfault.
- * This check prevents it
- */
-
- if (options->file == NULL)
- {
- if ((options->file = fopen(options->current_log, "a")) == NULL)
- {
- return -1;
- }
- }
-
if (fwrite(mem, mlen, 1, options->file) != 1)
{
return -1;
@@ -709,6 +681,9 @@ int el_file_putb
errno = EBADF;
return -1;
}
+
+ fseek(options->file, 0, SEEK_END);
+ options->fpos = ftell(options->file);
#endif /* HAVE_FSYNC && HAVE_FILENO */
#ifdef RUN_TESTS
diff --git a/tst/test-el-file.c b/tst/test-el-file.c
index daa954b..dd13683 100644
--- a/tst/test-el-file.c
+++ b/tst/test-el-file.c
@@ -880,20 +880,22 @@ static void file_rotate_5_hole_in_log_rotate(void)
el_puts("123");
mt_fok(file_check(WORKDIR"/log.0", "qaz"));
- mt_fok(file_check(WORKDIR"/log.1", "edc"));
- mt_fok(file_check(WORKDIR"/log.2", "rfv"));
+ mt_fok(file_check(WORKDIR"/log.2", "edc"));
+ mt_fok(file_check(WORKDIR"/log.3", "rfv"));
mt_fok(file_check(WORKDIR"/log.4", "123"));
el_puts("456");
- mt_fok(file_check(WORKDIR"/log.0", "edc"));
- mt_fok(file_check(WORKDIR"/log.1", "rfv"));
+ mt_fok(file_check(WORKDIR"/log.0", "qaz"));
+ mt_fok(file_check(WORKDIR"/log.1", "edc"));
+ mt_fok(file_check(WORKDIR"/log.2", "rfv"));
mt_fok(file_check(WORKDIR"/log.3", "123"));
mt_fok(file_check(WORKDIR"/log.4", "456"));
el_puts("789");
- mt_fok(file_check(WORKDIR"/log.0", "rfv"));
+ mt_fok(file_check(WORKDIR"/log.0", "edc"));
+ mt_fok(file_check(WORKDIR"/log.1", "rfv"));
mt_fok(file_check(WORKDIR"/log.2", "123"));
mt_fok(file_check(WORKDIR"/log.3", "456"));
mt_fok(file_check(WORKDIR"/log.4", "789"));
@@ -956,6 +958,309 @@ static void file_rotate_5_rename_file_halfway(void)
========================================================================== */
+static void file_rotate_directory_deleted(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+ mt_fok(el_option(EL_FPATH, WORKDIR"/log"));
+
+ el_puts("qaz");
+ el_puts("wsx");
+ el_puts("edc");
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ rmdir(WORKDIR);
+ mt_ferr(el_puts("rfv"), ENOENT);
+
+ mkdir(WORKDIR, 0755);
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_directory_reappear_after_delete(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+ mt_fok(el_option(EL_FPATH, WORKDIR"/log"));
+
+ el_puts("qaz");
+ el_puts("wsx");
+ el_puts("edc");
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ rmdir(WORKDIR);
+ mt_ferr(el_puts("rfv"), ENOENT);
+
+ mkdir(WORKDIR, 0755);
+
+ mt_fok(el_puts("rfv"));
+ mt_fok(el_puts("tgb"));
+ mt_fok(el_puts("yhn"));
+ mt_fok(el_puts("ujm"));
+ mt_fok(file_check(WORKDIR"/log.0", "rfv"));
+ mt_fok(file_check(WORKDIR"/log.1", "tgb"));
+ mt_fok(file_check(WORKDIR"/log.2", "yhn"));
+ mt_fok(file_check(WORKDIR"/log.3", "ujm"));
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ unlink(WORKDIR"/log.3");
+ unlink(WORKDIR"/log.4");
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_write_after_failed_open(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+
+ rmdir(WORKDIR);
+ mt_ferr(el_option(EL_FPATH, WORKDIR"/log"), ENOENT);
+ mkdir(WORKDIR, 0755);
+ mt_fok(el_puts("qaz"));
+ mt_fok(file_check(WORKDIR"/log.0", "qaz"));
+
+ unlink(WORKDIR"/log.0");
+ el_cleanup();
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_write_after_failed_open_to_existing_file(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+
+ rmdir(WORKDIR);
+ mt_ferr(el_option(EL_FPATH, WORKDIR"/log"), ENOENT);
+ mkdir(WORKDIR, 0755);
+ mt_fok(system("echo -n qaz > \""WORKDIR"/log.0\""));
+ mt_fok(system("echo -n ws > \""WORKDIR"/log.1\""));
+ mt_fok(el_puts("edc"));
+ mt_fok(file_check(WORKDIR"/log.0", "qaz"));
+ mt_fok(file_check(WORKDIR"/log.1", "ws"));
+ mt_fok(file_check(WORKDIR"/log.2", "edc"));
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ el_cleanup();
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_write_after_failed_open_to_existing_file_with_holes(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+
+ rmdir(WORKDIR);
+ mt_ferr(el_option(EL_FPATH, WORKDIR"/log"), ENOENT);
+ mkdir(WORKDIR, 0755);
+ mt_fok(system("echo -n qaz > \""WORKDIR"/log.0\""));
+ mt_fok(system("echo -n ws > \""WORKDIR"/log.2\""));
+ mt_fok(system("echo -n e > \""WORKDIR"/log.4\""));
+ mt_fok(el_puts("123"));
+ mt_fok(el_puts("456"));
+
+ mt_fok(file_check(WORKDIR"/log.0", "ws"));
+ mt_fok(file_check(WORKDIR"/log.2", "e"));
+ mt_fok(file_check(WORKDIR"/log.3", "123"));
+ mt_fok(file_check(WORKDIR"/log.4", "456"));
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ unlink(WORKDIR"/log.3");
+ unlink(WORKDIR"/log.4");
+ el_cleanup();
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_write_after_failed_open_to_existing_file_with_holes2(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+
+ rmdir(WORKDIR);
+ mt_ferr(el_option(EL_FPATH, WORKDIR"/log"), ENOENT);
+ mkdir(WORKDIR, 0755);
+ mt_fok(system("echo -n qaz > \""WORKDIR"/log.0\""));
+ mt_fok(system("echo -n ws > \""WORKDIR"/log.3\""));
+ mt_fok(system("echo -n e > \""WORKDIR"/log.4\""));
+ mt_fok(el_puts("123"));
+ mt_fok(el_puts("456"));
+
+ mt_fok(file_check(WORKDIR"/log.0", "qaz"));
+ mt_fok(file_check(WORKDIR"/log.1", "ws"));
+ mt_fok(file_check(WORKDIR"/log.2", "e"));
+ mt_fok(file_check(WORKDIR"/log.3", "123"));
+ mt_fok(file_check(WORKDIR"/log.4", "456"));
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ unlink(WORKDIR"/log.3");
+ unlink(WORKDIR"/log.4");
+ el_cleanup();
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_write_after_failed_open_to_existing_file_with_holes3(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+
+ rmdir(WORKDIR);
+ mt_ferr(el_option(EL_FPATH, WORKDIR"/log"), ENOENT);
+ mkdir(WORKDIR, 0755);
+ mt_fok(system("echo -n qaz > \""WORKDIR"/log.1\""));
+ mt_fok(system("echo -n ws > \""WORKDIR"/log.3\""));
+ mt_fok(system("echo -n e > \""WORKDIR"/log.4\""));
+ mt_fok(el_puts("123"));
+ mt_fok(el_puts("456"));
+ mt_fok(el_puts("789"));
+ mt_fok(file_check(WORKDIR"/log.0", "ws"));
+ mt_fok(file_check(WORKDIR"/log.1", "e"));
+ mt_fok(file_check(WORKDIR"/log.2", "123"));
+ mt_fok(file_check(WORKDIR"/log.3", "456"));
+ mt_fok(file_check(WORKDIR"/log.4", "789"));
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ unlink(WORKDIR"/log.3");
+ unlink(WORKDIR"/log.4");
+ el_cleanup();
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
+static void file_rotate_and_directory_reappear(void)
+{
+ /*
+ * mt_prepare_test not running here
+ */
+
+ el_init();
+ el_option(EL_OUT, EL_OUT_FILE);
+ el_option(EL_FILE_SYNC_EVERY, 0);
+ el_option(EL_FROTATE_SIZE, 3);
+ el_option(EL_FROTATE_NUMBER, 5);
+ mt_fok(el_option(EL_FPATH, WORKDIR"/log"));
+
+ mt_fok(el_puts("123"));
+ mt_fok(el_puts("456"));
+ mt_fok(el_puts("789"));
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+
+ rmdir(WORKDIR);
+ mt_ferr(el_puts(s9), ENOENT);
+ mkdir(WORKDIR, 0755);
+
+ mt_fok(system("echo -n 123 > \""WORKDIR"/log.0\""));
+ mt_fok(system("echo -n 456 > \""WORKDIR"/log.1\""));
+ mt_fok(system("echo -n 789 > \""WORKDIR"/log.2\""));
+
+ mt_fok(el_puts("qaz"));
+ mt_fok(file_check(WORKDIR"/log.0", "123"));
+ mt_fok(file_check(WORKDIR"/log.1", "456"));
+ mt_fok(file_check(WORKDIR"/log.2", "789"));
+ mt_fok(file_check(WORKDIR"/log.3", "qaz"));
+
+ unlink(WORKDIR"/log.0");
+ unlink(WORKDIR"/log.1");
+ unlink(WORKDIR"/log.2");
+ unlink(WORKDIR"/log.3");
+ unlink(WORKDIR"/log.4");
+ el_cleanup();
+}
+
+
+/* ==========================================================================
+ ========================================================================== */
+
+
static void file_no_dir_for_logs(void)
{
mt_ferr(el_option(EL_FPATH, "/tmp/i-dont/exist"), ENOENT);
@@ -1069,29 +1374,29 @@ static void file_rotate_dir_removed_after_open_then_created_back_again(void)
mt_fok(el_puts(s8));
mt_fok(el_puts(s5));
- mt_fok(file_check(WORKDIR"/log.2", s8 s5));
+ mt_fok(file_check(WORKDIR"/log.0", s8 s5));
mt_fok(el_puts(s8));
mt_fok(el_puts(s3));
mt_fok(el_puts(s5));
- mt_fok(file_check(WORKDIR"/log.2", s8 s5));
- mt_fok(file_check(WORKDIR"/log.3", s8 s3 s5));
+ mt_fok(file_check(WORKDIR"/log.0", s8 s5));
+ mt_fok(file_check(WORKDIR"/log.1", s8 s3 s5));
mt_fok(el_puts(s9));
mt_fok(el_puts(s5));
- mt_fok(file_check(WORKDIR"/log.2", s8 s5));
- mt_fok(file_check(WORKDIR"/log.3", s8 s3 s5));
- mt_fok(file_check(WORKDIR"/log.4", s9 s5));
+ mt_fok(file_check(WORKDIR"/log.0", s8 s5));
+ mt_fok(file_check(WORKDIR"/log.1", s8 s3 s5));
+ mt_fok(file_check(WORKDIR"/log.2", s9 s5));
mt_fok(el_puts(s3));
mt_fok(el_puts(s8));
- mt_fok(file_check(WORKDIR"/log.1", s8 s5));
- mt_fok(file_check(WORKDIR"/log.2", s8 s3 s5));
- mt_fok(file_check(WORKDIR"/log.3", s9 s5));
- mt_fok(file_check(WORKDIR"/log.4", s3 s8));
+ mt_fok(file_check(WORKDIR"/log.0", s8 s5));
+ mt_fok(file_check(WORKDIR"/log.1", s8 s3 s5));
+ mt_fok(file_check(WORKDIR"/log.2", s9 s5));
+ mt_fok(file_check(WORKDIR"/log.3", s3 s8));
}
@@ -1209,7 +1514,7 @@ static void file_rotate_fail(void)
mkdir(WORKDIR, 0755);
mt_fok(el_puts(s8));
- mt_fok(file_check(WORKDIR"/log.1", s8));
+ mt_fok(file_check(WORKDIR"/log.0", s8));
}
@@ -1323,6 +1628,14 @@ void el_file_test_group(void)
mt_run(file_print_without_setting_file);
mt_run(file_write_after_failed_open);
mt_run(file_write_after_failed_open_to_existing_file);
+ mt_run(file_rotate_directory_deleted);
+ mt_run(file_rotate_directory_reappear_after_delete);
+ mt_run(file_rotate_write_after_failed_open);
+ mt_run(file_rotate_write_after_failed_open_to_existing_file);
+ mt_run(file_rotate_write_after_failed_open_to_existing_file_with_holes);
+ mt_run(file_rotate_write_after_failed_open_to_existing_file_with_holes2);
+ mt_run(file_rotate_write_after_failed_open_to_existing_file_with_holes3);
+ mt_run(file_rotate_and_directory_reappear);
mt_prepare_test = &test_prepare;
mt_cleanup_test = &test_cleanup;