summaryrefslogtreecommitdiff
path: root/src/test/test-fs-util.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-12-27 16:20:28 +0100
committerLennart Poettering <lennart@poettering.net>2018-01-05 13:55:08 +0100
commit9e3fa6e82773cb1d8687453ef0ba0ad9e5dda7d2 (patch)
tree6ffb7f341c8cd68a22aee71225ddf3e967ca6d2c /src/test/test-fs-util.c
parent5ae37ad833583e6c1c7765767b7f8360afca3b07 (diff)
downloadsystemd-9e3fa6e82773cb1d8687453ef0ba0ad9e5dda7d2.tar.gz
fs-util: rework touch_file() so that it can touch socket file nodes
Let's rework touch_file() so that it works correctly on sockets, fifos, and device nodes: let's open an O_PATH file descriptor first and operate based on that, if we can. This is usually the better option as it this means we can open AF_UNIX nodes in the file system, and update their timestamps and ownership correctly. It also means we can correctly touch symlinks and block/character devices without triggering their drivers. Moreover, by operating on an O_PATH fd we can make sure that we operate on the same inode the whole time, and it can't be swapped out in the middle. While we are at it, rework the call so that we try to adjust as much as we can before returning on error. This is a good idea as we call the function quite often without checking its result, and hence it's best to leave the files around in the most "correct" fashion possible.
Diffstat (limited to 'src/test/test-fs-util.c')
-rw-r--r--src/test/test-fs-util.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/test/test-fs-util.c b/src/test/test-fs-util.c
index 86d963c4c7..2ad9e71856 100644
--- a/src/test/test-fs-util.c
+++ b/src/test/test-fs-util.c
@@ -388,6 +388,92 @@ static void test_access_fd(void) {
}
}
+static void test_touch_file(void) {
+ uid_t test_uid, test_gid;
+ _cleanup_(rm_rf_physical_and_freep) char *p = NULL;
+ struct stat st;
+ const char *a;
+ usec_t test_mtime;
+
+ test_uid = geteuid() == 0 ? 65534 : getuid();
+ test_gid = geteuid() == 0 ? 65534 : getgid();
+
+ test_mtime = usec_sub_unsigned(now(CLOCK_REALTIME), USEC_PER_WEEK);
+
+ assert_se(mkdtemp_malloc("/dev/shm/touch-file-XXXXXX", &p) >= 0);
+
+ a = strjoina(p, "/regular");
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISREG(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/dir");
+ assert_se(mkdir(a, 0775) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISDIR(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/fifo");
+ assert_se(mkfifo(a, 0775) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISFIFO(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/sock");
+ assert_se(mknod(a, 0775 | S_IFSOCK, 0) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISSOCK(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ if (geteuid() == 0) {
+ a = strjoina(p, "/cdev");
+ assert_se(mknod(a, 0775 | S_IFCHR, makedev(0, 0)) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISCHR(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+
+ a = strjoina(p, "/bdev");
+ assert_se(mknod(a, 0775 | S_IFBLK, makedev(0, 0)) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISBLK(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+ }
+
+ a = strjoina(p, "/lnk");
+ assert_se(symlink("target", a) >= 0);
+ assert_se(touch_file(a, false, test_mtime, test_uid, test_gid, 0640) >= 0);
+ assert_se(lstat(a, &st) >= 0);
+ assert_se(st.st_uid == test_uid);
+ assert_se(st.st_gid == test_gid);
+ assert_se(S_ISLNK(st.st_mode));
+ assert_se((st.st_mode & 0777) == 0640);
+ assert_se(timespec_load(&st.st_mtim) == test_mtime);
+}
+
int main(int argc, char *argv[]) {
test_unlink_noerrno();
test_get_files_in_directory();
@@ -396,6 +482,7 @@ int main(int argc, char *argv[]) {
test_chase_symlinks();
test_dot_or_dot_dot();
test_access_fd();
+ test_touch_file();
return 0;
}