File U_06-Add-rmdir_recursive.patch of Package slurm.32313
From: Tim Wickberg <tim@schedmd.com>
Date: Wed Oct 11 12:45:25 2023 -0600
Subject: [PATCH 6/19]Add rmdir_recursive().
Patch-mainline: Upstream
Git-repo: https://github.com/SchedMD/slurm
Git-commit: bcb5eb7d376a46c8935d9b7479272e9cd5c366c3
References: bsc#1216207
Signed-off-by: Egbert Eich <eich@suse.de>
---
src/common/fd.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++
src/common/fd.h | 9 +++++
src/common/slurm_xlator.h | 1 +
3 files changed, 101 insertions(+)
diff --git a/src/common/fd.c b/src/common/fd.c
index 2c45f0e089..9b3b52c9f4 100644
--- a/src/common/fd.c
+++ b/src/common/fd.c
@@ -35,6 +35,7 @@
* Refer to "fd.h" for documentation on public functions.
\*****************************************************************************/
+#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
@@ -62,6 +63,7 @@ strong_alias(fd_set_nonblocking,slurm_fd_set_nonblocking);
strong_alias(fd_get_socket_error, slurm_fd_get_socket_error);
strong_alias(send_fd_over_pipe, slurm_send_fd_over_pipe);
strong_alias(receive_fd_over_pipe, slurm_receive_fd_over_pipe);
+strong_alias(rmdir_recursive, slurm_rmdir_recursive);
static int fd_get_lock(int fd, int cmd, int type);
static pid_t fd_test_lock(int fd, int type);
@@ -375,3 +377,92 @@ extern int receive_fd_over_pipe(int socket)
return fd;
}
+
+static int _rmdir_recursive(int dirfd)
+{
+ int rc = 0;
+ DIR *dp;
+ struct dirent *ent;
+
+ if (!(dp = fdopendir(dirfd))) {
+ error("%s: can't open directory: %m", __func__);
+ return 1;
+ }
+
+ while ((ent = readdir(dp))) {
+ int childfd = -1;
+
+ /* skip special directories */
+ if (!strcmp(ent->d_name, ".") ||
+ !strcmp(ent->d_name, "..")) {
+ continue;
+ }
+
+ /* try to remove entry, first as a file, then as a directory */
+ if (unlinkat(dirfd, ent->d_name, 0) != -1) {
+ debug("%s: removed file `%s`", __func__, ent->d_name);
+ continue;
+ } else if (unlinkat(dirfd, ent->d_name, AT_REMOVEDIR) != -1) {
+ debug("%s: removed empty directory `%s`",
+ __func__, ent->d_name);
+ continue;
+ }
+
+ /* removal didn't work. assume it's a non-empty directory */
+ if ((childfd = openat(dirfd, ent->d_name,
+ (O_DIRECTORY | O_NOFOLLOW))) < 0) {
+ debug("%s: openat() failed for `%s`: %m",
+ __func__, ent->d_name);
+ rc++;
+ continue;
+ }
+
+ debug("%s: descending into directory `%s`",
+ __func__, ent->d_name);
+ rc += _rmdir_recursive(childfd);
+ (void) close(childfd);
+
+ if (unlinkat(dirfd, ent->d_name, AT_REMOVEDIR) != -1) {
+ debug("%s: removed now-empty directory `%s`",
+ __func__, ent->d_name);
+ } else {
+ debug("%s: unlinkat() failed for `%s`: %m",
+ __func__, ent->d_name);
+ rc++;
+ }
+ }
+ closedir(dp);
+
+ return rc;
+}
+
+extern int rmdir_recursive(const char *path, bool remove_top)
+{
+ int rc = 0;
+ int dirfd;
+
+ if ((dirfd = open(path, O_DIRECTORY | O_NOFOLLOW)) < 0) {
+ error("%s: could not open %s", __func__, path);
+ return 1;
+ }
+
+ rc = _rmdir_recursive(dirfd);
+ close(dirfd);
+
+ if (remove_top) {
+ if (rmdir(path) < 0) {
+ debug("%s: rmdir() failed for `%s`: %m",
+ __func__, path);
+ rc++;
+ } else {
+ debug("%s: removed now-empty top directory `%s`",
+ __func__, path);
+ }
+ }
+
+ if (rc)
+ error("%s: could not completely remove `%s`, %d files left",
+ __func__, path, rc);
+
+ return rc;
+}
diff --git a/src/common/fd.h b/src/common/fd.h
index f483c78e1c..5f9788b3e4 100644
--- a/src/common/fd.h
+++ b/src/common/fd.h
@@ -159,4 +159,13 @@ extern char *poll_revents_to_str(const short revents);
extern void send_fd_over_pipe(int socket, int fd);
extern int receive_fd_over_pipe(int socket);
+/*
+ * Recursively remove a directory and all contents.
+ * Takes care not to follow any symlinks outside the target directory.
+ *
+ * Returns the number of files/directories it failed to remove,
+ * or 0 on success.
+ */
+extern int rmdir_recursive(const char *path, bool remove_top);
+
#endif /* !_FD_H */
diff --git a/src/common/slurm_xlator.h b/src/common/slurm_xlator.h
index ebec4137a5..552899c612 100644
--- a/src/common/slurm_xlator.h
+++ b/src/common/slurm_xlator.h
@@ -116,6 +116,7 @@
#define fd_set_nonblocking slurm_fd_set_nonblocking
#define send_fd_over_pipe slurm_send_fd_over_pipe
#define receive_fd_over_pipe slurm_receive_fd_over_pipe
+#define rmdir_recursive slurm_rmdir_recursive
/* hostlist.[ch] functions */
#define hostlist_create slurm_hostlist_create