]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
vmspawn: Create journal parent directories if needed
authorDaan De Meyer <daan@amutable.com>
Wed, 25 Mar 2026 09:22:30 +0000 (10:22 +0100)
committerDaan De Meyer <daan.j.demeyer@gmail.com>
Wed, 25 Mar 2026 20:55:19 +0000 (21:55 +0100)
src/test/test-chase.c
src/vmspawn/vmspawn.c

index 129ea19b7237d23ba8047c5997b5ef735bf7ce50..721f56a250663087fb576cfade9525f7ab25dddf 100644 (file)
@@ -620,6 +620,16 @@ TEST(chaseat) {
 
         assert_se(chaseat(tfd, "i/../p", CHASE_MKDIR_0755|CHASE_NONEXISTENT, NULL, NULL) == -ENOENT);
 
+        /* Test CHASE_MKDIR_0755|CHASE_PARENT — creates intermediate dirs but not the final component */
+
+        ASSERT_OK(chaseat(tfd, "mkp/a/r/e/n/t/file", CHASE_MKDIR_0755|CHASE_PARENT, &result, &fd));
+        ASSERT_OK(faccessat(tfd, "mkp/a/r/e/n/t", F_OK, 0));
+        assert_se(RET_NERRNO(faccessat(tfd, "mkp/a/r/e/n/t/file", F_OK, 0)) == -ENOENT);
+        ASSERT_OK(fd_verify_directory(fd));
+        fd = safe_close(fd);
+        ASSERT_STREQ(result, "mkp/a/r/e/n/t/file");
+        result = mfree(result);
+
         /* Test CHASE_EXTRACT_FILENAME */
 
         ASSERT_OK(chaseat(tfd, "chase/parent", CHASE_AT_RESOLVE_IN_ROOT|CHASE_PARENT|CHASE_NOFOLLOW|CHASE_EXTRACT_FILENAME, &result, &fd));
@@ -664,6 +674,23 @@ TEST(chaseat) {
         fd = safe_close(fd);
         result = mfree(result);
 
+        /* Test chase_and_openat() with CHASE_MKDIR_0755|CHASE_PARENT — opens parent dir */
+
+        fd = chase_and_openat(tfd, "mkopen/p/a/r/file.txt", CHASE_MKDIR_0755|CHASE_PARENT, O_RDONLY|O_CLOEXEC, NULL);
+        ASSERT_OK(fd);
+        ASSERT_OK(fd_verify_directory(fd));
+        ASSERT_OK(faccessat(tfd, "mkopen/p/a/r", F_OK, 0));
+        assert_se(RET_NERRNO(faccessat(tfd, "mkopen/p/a/r/file.txt", F_OK, 0)) == -ENOENT);
+        fd = safe_close(fd);
+
+        /* Test chase_and_openat() with CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY + O_CREAT — creates and opens target dir */
+
+        fd = chase_and_openat(tfd, "mkopen/d/i/r/target", CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY, O_CREAT|O_RDONLY|O_CLOEXEC, NULL);
+        ASSERT_OK(fd);
+        ASSERT_OK(fd_verify_directory(fd));
+        ASSERT_OK(faccessat(tfd, "mkopen/d/i/r/target", F_OK, 0));
+        fd = safe_close(fd);
+
         /* Test chase_and_openatdir() */
 
         ASSERT_OK(chase_and_opendirat(tfd, "o/p/e/n/d/i", 0, &result, &dir));
index a197132c0434d2980386af4e345deefc68bd3d0d..f730a756e28edbaa3fa453fecb69227949dc876f 100644 (file)
@@ -26,6 +26,8 @@
 #include "bus-locator.h"
 #include "bus-util.h"
 #include "capability-util.h"
+#include "chase.h"
+#include "chattr-util.h"
 #include "common-signal.h"
 #include "copy.h"
 #include "discover-image.h"
@@ -2953,6 +2955,19 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) {
         if (arg_forward_journal) {
                 _cleanup_free_ char *listen_address = NULL;
 
+                ChaseFlags chase_flags = CHASE_MKDIR_0755|CHASE_MUST_BE_DIRECTORY;
+                if (endswith(arg_forward_journal, ".journal"))
+                        chase_flags |= CHASE_PARENT;
+
+                _cleanup_close_ int journal_fd = -EBADF;
+                r = chase(arg_forward_journal, /* root= */ NULL, chase_flags, /* ret_path= */ NULL, &journal_fd);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to create journal directory for '%s': %m", arg_forward_journal);
+
+                r = chattr_fd(journal_fd, FS_NOCOW_FL, FS_NOCOW_FL);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to set NOCOW flag on journal directory for '%s', ignoring: %m", arg_forward_journal);
+
                 if (!GREEDY_REALLOC(children, n_children + 1))
                         return log_oom();