richardphibel / rpms / libdnf

Forked from rpms/libdnf 2 years ago
Clone
885e9e
From d66dfc2815153b315f5b3fd9d3f93be670def26a Mon Sep 17 00:00:00 2001
885e9e
From: Jaroslav Rohel <jrohel@redhat.com>
885e9e
Date: Tue, 3 Sep 2019 12:55:51 +0200
885e9e
Subject: [PATCH 09/10] Added dnf_move_recursive()
885e9e
885e9e
Moves a directory and its contents. If native move operations are
885e9e
supported then this is used, otherwise a copy + delete fallback is used.
885e9e
---
885e9e
 libdnf/hy-iutil-private.hpp |  1 +
885e9e
 libdnf/hy-iutil.cpp         | 95 +++++++++++++++++++++++++++++++++++--
885e9e
 2 files changed, 93 insertions(+), 3 deletions(-)
885e9e
885e9e
diff --git a/libdnf/hy-iutil-private.hpp b/libdnf/hy-iutil-private.hpp
885e9e
index 8b2b06d5..4920ad39 100644
885e9e
--- a/libdnf/hy-iutil-private.hpp
885e9e
+++ b/libdnf/hy-iutil-private.hpp
885e9e
@@ -41,6 +41,7 @@ char *abspath(const char *path);
885e9e
 int is_readable_rpm(const char *fn);
885e9e
 int mkcachedir(char *path);
885e9e
 gboolean mv(const char *old_path, const char *new_path, GError **error);
885e9e
+gboolean dnf_move_recursive(const gchar *src_dir, const gchar *dst_dir, GError **error);
885e9e
 char *this_username(void);
885e9e
 
885e9e
 /* misc utils */
885e9e
diff --git a/libdnf/hy-iutil.cpp b/libdnf/hy-iutil.cpp
885e9e
index 2c5af481..d3b57c79 100644
885e9e
--- a/libdnf/hy-iutil.cpp
885e9e
+++ b/libdnf/hy-iutil.cpp
885e9e
@@ -20,12 +20,14 @@
885e9e
 
885e9e
 #include <assert.h>
885e9e
 #include <errno.h>
885e9e
+#include <dirent.h>
885e9e
 #include <fcntl.h>
885e9e
 #include <linux/limits.h>
885e9e
 #include <pwd.h>
885e9e
 #include <unistd.h>
885e9e
 #include <stdio.h>
885e9e
 #include <stdlib.h>
885e9e
+#include <string.h>
885e9e
 #include <sys/stat.h>
885e9e
 #include <sys/types.h>
885e9e
 #include <sys/utsname.h>
885e9e
@@ -41,9 +43,6 @@ extern "C" {
885e9e
 #include <solv/pool_parserpmrichdep.h>
885e9e
 }
885e9e
 
885e9e
-// glib
885e9e
-#include <glib.h>
885e9e
-
885e9e
 // hawkey
885e9e
 #include "dnf-advisory-private.hpp"
885e9e
 #include "dnf-types.h"
885e9e
@@ -58,6 +57,12 @@ extern "C" {
885e9e
 #include "utils/bgettext/bgettext-lib.h"
885e9e
 #include "sack/packageset.hpp"
885e9e
 
885e9e
+// glib
885e9e
+#include <glib.h>
885e9e
+#include <gio/gio.h>
885e9e
+
885e9e
+#include <string>
885e9e
+
885e9e
 #define BUF_BLOCK 4096
885e9e
 #define CHKSUM_TYPE REPOKEY_TYPE_SHA256
885e9e
 #define CHKSUM_IDENT "H000"
885e9e
@@ -328,6 +333,90 @@ mv(const char* old_path, const char* new_path, GError** error)
885e9e
     return TRUE;
885e9e
 }
885e9e
 
885e9e
+static gboolean
885e9e
+copyFile(const std::string & srcPath, const std::string & dstPath, GError ** error)
885e9e
+{
885e9e
+    g_autoptr(GFile) src = g_file_new_for_path(srcPath.c_str());
885e9e
+    g_autoptr(GFile) dest = g_file_new_for_path(dstPath.c_str());
885e9e
+    return g_file_copy(src, dest,
885e9e
+        static_cast<GFileCopyFlags>(G_FILE_COPY_NOFOLLOW_SYMLINKS | G_FILE_COPY_ALL_METADATA)
885e9e
+        , NULL, NULL, NULL, error);
885e9e
+}
885e9e
+
885e9e
+static gboolean
885e9e
+copyRecursive(const std::string & srcPath, const std::string & dstPath, GError ** error)
885e9e
+{
885e9e
+    struct stat info;
885e9e
+    if (!stat(srcPath.c_str(), &info)) {
885e9e
+        if (S_ISDIR(info.st_mode)) {
885e9e
+            if (mkdir(dstPath.c_str(), info.st_mode) == -1) {
885e9e
+                auto err = errno;
885e9e
+                g_set_error(error,
885e9e
+                    DNF_ERROR,
885e9e
+                    DNF_ERROR_INTERNAL_ERROR,
885e9e
+                    _("cannot create directory %1$s: %2$s"),
885e9e
+                    dstPath.c_str(), strerror(err));
885e9e
+                return FALSE;
885e9e
+            }
885e9e
+            if (auto fd = opendir(srcPath.c_str())) {
885e9e
+                int ret = TRUE;
885e9e
+                while (auto dent = readdir(fd)) {
885e9e
+                    auto name = dent->d_name;
885e9e
+                    if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')))
885e9e
+                        continue;
885e9e
+                    std::string srcItem = srcPath + "/" + name;
885e9e
+                    std::string dstItem = dstPath + "/" + name;
885e9e
+                    ret = copyRecursive(srcItem, dstItem, error);
885e9e
+                    if (!ret)
885e9e
+                        break;
885e9e
+                }
885e9e
+                closedir(fd);
885e9e
+                return ret;
885e9e
+            } else {
885e9e
+                auto err = errno;
885e9e
+                g_set_error(error,
885e9e
+                    DNF_ERROR,
885e9e
+                    DNF_ERROR_INTERNAL_ERROR,
885e9e
+                    _("cannot open directory %1$s: %2$s"),
885e9e
+                    srcPath.c_str(), strerror(err));
885e9e
+                return FALSE;
885e9e
+            }
885e9e
+        } else {
885e9e
+            return copyFile(srcPath, dstPath, error);
885e9e
+        }
885e9e
+    } else {
885e9e
+        auto err = errno;
885e9e
+        g_set_error(error,
885e9e
+            DNF_ERROR,
885e9e
+            DNF_ERROR_INTERNAL_ERROR,
885e9e
+            _("cannot stat path %1$s: %2$s"),
885e9e
+            srcPath.c_str(), strerror(err));
885e9e
+        return FALSE;
885e9e
+    }
885e9e
+}
885e9e
+
885e9e
+/**
885e9e
+ * dnf_move_recursive:
885e9e
+ * @src_dir: A source directory path
885e9e
+ * @dst_dir: A destination directory path
885e9e
+ * @error: A #GError, or %NULL
885e9e
+ *
885e9e
+ * Moves a directory and its contents. Native move is preferred,
885e9e
+ * if not supported copy and delete fallback is used.
885e9e
+ *
885e9e
+ * Returns: %TRUE on successful move, %FALSE otherwise
885e9e
+ **/
885e9e
+gboolean
885e9e
+dnf_move_recursive(const char * srcDir, const char * dstDir, GError ** error)
885e9e
+{
885e9e
+    if (rename(srcDir, dstDir) == -1) {
885e9e
+        if (!copyRecursive(srcDir, dstDir, error))
885e9e
+            return FALSE;
885e9e
+        return dnf_remove_recursive(srcDir, error);
885e9e
+    }
885e9e
+    return TRUE;
885e9e
+}
885e9e
+
885e9e
 char *
885e9e
 this_username(void)
885e9e
 {
885e9e
-- 
885e9e
2.21.0
885e9e