diff options
author | Lennart Poettering <lennart@poettering.net> | 2020-11-18 15:11:43 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2020-12-02 10:32:17 +0100 |
commit | 1098142436f46b889f6b7bcc87af54bc5b95d560 (patch) | |
tree | b1a21013091eddad2aee5bc9c4fb3e8bc104d803 /src/test/test-fs-util.c | |
parent | copy: teach copy_file() that a mode=-1 call means "take mode from original file" (diff) | |
download | systemd-1098142436f46b889f6b7bcc87af54bc5b95d560.tar.xz systemd-1098142436f46b889f6b7bcc87af54bc5b95d560.zip |
fs-util: add conservative_rename() that suppresses unnecessary renames
if the source and destination file match in contents and basic file
attributes, don#t rename, but just remove source.
This is a simple way to suppress inotify events + mtime changes when
atomically updating files.
Diffstat (limited to 'src/test/test-fs-util.c')
-rw-r--r-- | src/test/test-fs-util.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c index d1f9252521..e0ef8257bd 100644 --- a/src/test/test-fs-util.c +++ b/src/test/test-fs-util.c @@ -3,7 +3,9 @@ #include <unistd.h> #include "alloc-util.h" +#include "copy.h" #include "fd-util.h" +#include "fileio.h" #include "fs-util.h" #include "id128-util.h" #include "macro.h" @@ -834,6 +836,51 @@ static void test_path_is_encrypted(void) { test_path_is_encrypted_one("/dev", booted > 0 ? false : -1); } +static void test_conservative_rename(void) { + _cleanup_(unlink_and_freep) char *p = NULL; + _cleanup_free_ char *q = NULL; + + assert_se(tempfn_random_child(NULL, NULL, &p) >= 0); + assert_se(write_string_file(p, "this is a test", WRITE_STRING_FILE_CREATE) >= 0); + + assert_se(tempfn_random_child(NULL, NULL, &q) >= 0); + + /* Check that the hardlinked "copy" is detected */ + assert_se(link(p, q) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); + + /* Check that a manual copy is detected */ + assert_se(copy_file(p, q, 0, (mode_t) -1, 0, 0, COPY_REFLINK) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); + + /* Check that a manual new writeout is also detected */ + assert_se(write_string_file(q, "this is a test", WRITE_STRING_FILE_CREATE) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); + + /* Check that a minimally changed version is detected */ + assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); + + /* Check that this really is new updated version */ + assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) == 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); + + /* Make sure we detect extended files */ + assert_se(write_string_file(q, "this is a_testx", WRITE_STRING_FILE_CREATE) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); + + /* Make sure we detect truncated files */ + assert_se(write_string_file(q, "this is a_test", WRITE_STRING_FILE_CREATE) >= 0); + assert_se(conservative_rename(AT_FDCWD, q, AT_FDCWD, p) > 0); + assert_se(access(q, F_OK) < 0 && errno == ENOENT); +} + int main(int argc, char *argv[]) { test_setup_logging(LOG_INFO); @@ -852,6 +899,7 @@ int main(int argc, char *argv[]) { test_rename_noreplace(); test_chmod_and_chown(); test_path_is_encrypted(); + test_conservative_rename(); return 0; } |