From: Mike Yuan Date: Tue, 7 May 2024 12:13:55 +0000 (+0800) Subject: basic/mkdir: use timespec_store instead of _nsec for mkdir_p_root_full X-Git-Tag: v256-rc2~80^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=158681f0f97d1efe9c7edf06aa86230964b8d0e6;p=thirdparty%2Fsystemd.git basic/mkdir: use timespec_store instead of _nsec for mkdir_p_root_full Follow-up for 34c3d574742e867ef97e79509e4051a82f1b7d9b O_RDONLY is dropped when O_DIRECTORY is specified, since it's unnecessary and even arguably confusing here, as the dir is modified. --- diff --git a/src/basic/mkdir.c b/src/basic/mkdir.c index c378f896041..20329e04c2d 100644 --- a/src/basic/mkdir.c +++ b/src/basic/mkdir.c @@ -209,6 +209,8 @@ int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mod _cleanup_close_ int dfd = -EBADF; int r; + assert(p); + r = path_extract_directory(p, &pp); if (r == -EDESTADDRREQ) { /* only fname is passed, no prefix to operate on */ @@ -226,7 +228,7 @@ int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mod if (r < 0) return r; - dfd = chase_and_open(pp, root, CHASE_PREFIX_ROOT, O_RDONLY|O_CLOEXEC|O_DIRECTORY, NULL); + dfd = chase_and_open(pp, root, CHASE_PREFIX_ROOT, O_CLOEXEC|O_DIRECTORY, NULL); if (dfd < 0) return dfd; } @@ -241,25 +243,22 @@ int mkdir_p_root_full(const char *root, const char *p, uid_t uid, gid_t gid, mod r = btrfs_subvol_make_fallback(dfd, bn, m); else r = RET_NERRNO(mkdirat(dfd, bn, m)); - if (r < 0) { - if (r == -EEXIST) - return 0; - + if (r == -EEXIST) + return 0; + if (r < 0) return r; - } if (ts == USEC_INFINITY && !uid_is_valid(uid) && !gid_is_valid(gid)) return 1; - _cleanup_close_ int nfd = -EBADF; - nfd = openat(dfd, bn, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); + _cleanup_close_ int nfd = openat(dfd, bn, O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW); if (nfd < 0) return -errno; if (ts != USEC_INFINITY) { struct timespec tspec; + timespec_store(&tspec, ts); - timespec_store_nsec(&tspec, ts); if (futimens(dfd, (const struct timespec[2]) { { .tv_nsec = UTIME_OMIT }, tspec }) < 0) return -errno; diff --git a/src/test/test-mkdir.c b/src/test/test-mkdir.c index fcb8fc7a6b4..ef00729c08b 100644 --- a/src/test/test-mkdir.c +++ b/src/test/test-mkdir.c @@ -143,26 +143,26 @@ TEST(mkdir_p_root_full) { _cleanup_free_ char *p = NULL; struct stat st; - assert_se(mkdtemp_malloc("/tmp/test-mkdir-XXXXXX", &tmp) >= 0); - - assert_se(p = path_join(tmp, "foo")); - assert_se(mkdir_p_root_full(tmp, "/foo", UID_INVALID, GID_INVALID, 0755, 1234, NULL) >= 0); - assert_se(is_dir(p, false) > 0); - assert_se(is_dir(p, true) > 0); - assert_se(stat(p, &st) >= 0); - assert_se(st.st_mtim.tv_nsec == 1234); - assert_se(st.st_atim.tv_nsec == 1234); - - p = mfree(p); - assert_se(p = path_join(tmp, "dir-not-exists/foo")); - assert_se(mkdir_p_root_full(tmp, "/dir-not-exists/foo", UID_INVALID, GID_INVALID, 0755, 5678, NULL) >= 0); - assert_se(is_dir(p, false) > 0); - assert_se(is_dir(p, true) > 0); - p = mfree(p); - assert_se(p = path_join(tmp, "dir-not-exists")); - assert_se(stat(p, &st) >= 0); - assert_se(st.st_mtim.tv_nsec == 5678); - assert_se(st.st_atim.tv_nsec == 5678); + ASSERT_OK(mkdtemp_malloc("/tmp/test-mkdir-XXXXXX", &tmp)); + + ASSERT_NOT_NULL(p = path_join(tmp, "foo")); + ASSERT_OK(mkdir_p_root_full(tmp, "/foo", UID_INVALID, GID_INVALID, 0755, 2 * USEC_PER_SEC, NULL)); + ASSERT_GT(is_dir(p, false), 0); + ASSERT_GT(is_dir(p, true), 0); + ASSERT_OK_ERRNO(stat(p, &st)); + ASSERT_EQ(st.st_mtim.tv_sec, 2); + ASSERT_EQ(st.st_atim.tv_sec, 2); + + p = mfree(p); + ASSERT_NOT_NULL(p = path_join(tmp, "dir-not-exists/foo")); + ASSERT_OK(mkdir_p_root_full(NULL, p, UID_INVALID, GID_INVALID, 0755, 90 * USEC_PER_HOUR, NULL)); + ASSERT_GT(is_dir(p, false), 0); + ASSERT_GT(is_dir(p, true), 0); + p = mfree(p); + ASSERT_NOT_NULL(p = path_join(tmp, "dir-not-exists")); + ASSERT_OK_ERRNO(stat(p, &st)); + ASSERT_EQ(st.st_mtim.tv_sec, 90 * 60 * 60); + ASSERT_EQ(st.st_atim.tv_sec, 90 * 60 * 60); } DEFINE_TEST_MAIN(LOG_DEBUG);