From 37db6597daa992702b3a8a5b7a636f935e6861ba Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
Date: Sat, 18 Mar 2023 23:35:04 +0900
Subject: [PATCH] rm-rf: fix errno handling

(cherry picked from commit cd2cd095db6f26bf9889ef26f1b105843220b803)
(cherry picked from commit 80417f90b03707a873bbff89f246ece3fb9f2c95)
(cherry picked from commit 25a8b163be1558cc837af68baefac3c8f1ba3497)

Conflict:add function RET_NERRNO
Reference:https://github.com/systemd/systemd-stable/commit/37db6597daa992702b3a8a5b7a636f935e6861ba
---
 src/basic/errno-util.h | 23 +++++++++++++++++++++++
 src/shared/rm-rf.c     |  8 ++++----
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/src/basic/errno-util.h b/src/basic/errno-util.h
index ffa3e12..57071e5 100644
--- a/src/basic/errno-util.h
+++ b/src/basic/errno-util.h
@@ -31,6 +31,29 @@ static inline int negative_errno(void) {
         return -errno;
 }
 
+static inline int RET_NERRNO(int ret) {
+
+        /* Helper to wrap system calls in to make them return negative errno errors. This brings system call
+         * error handling in sync with how we usually handle errors in our own code, i.e. with immediate
+         * returning of negative errno. Usage is like this:
+         *
+         *     …
+         *     r = RET_NERRNO(unlink(t));
+         *     …
+         *
+         * or
+         *
+         *     …
+         *     fd = RET_NERRNO(open("/etc/fstab", O_RDONLY|O_CLOEXEC));
+         *     …
+         */
+
+        if (ret < 0)
+                return negative_errno();
+
+        return ret;
+}
+
 static inline const char *strerror_safe(int error) {
         /* 'safe' here does NOT mean thread safety. */
         return strerror(abs(error)); /* lgtm [cpp/potentially-dangerous-function] */
diff --git a/src/shared/rm-rf.c b/src/shared/rm-rf.c
index 954686f..58e54f6 100644
--- a/src/shared/rm-rf.c
+++ b/src/shared/rm-rf.c
@@ -288,8 +288,8 @@ int rm_rf_children(
                                  if (!newdirname)
                                          return log_oom();
 
-                                 int newfd = openat(fd, de->d_name,
-                                                    O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME);
+                                 int newfd = RET_NERRNO(openat(fd, de->d_name,
+                                                               O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME));
                                  if (newfd >= 0) {
                                          todos[n_todo++] = (TodoEntry) { TAKE_PTR(d), TAKE_PTR(dirname) };
                                          fd = newfd;
@@ -297,8 +297,8 @@ int rm_rf_children(
 
                                          goto next_fd;
 
-                                 } else if (errno != -ENOENT && ret == 0)
-                                         ret = -errno;
+                                 } else if (newfd != -ENOENT && ret == 0)
+                                         ret = newfd;
 
                         } else if (r < 0 && r != -ENOENT && ret == 0)
                                 ret = r;
-- 
2.33.0

