Blob Blame History Raw
From 99d35011a057a112957c6e878f4ac0b7ab0d0e7a Mon Sep 17 00:00:00 2001
From: Jaroslav Rohel <jrohel@redhat.com>
Date: Tue, 3 Sep 2019 13:13:31 +0200
Subject: [PATCH 10/10] Use copy+delete fallback if moving of directory failed
 (RhBug:1700341)

Uses dnf_move_recursive() instead of g_rename()/rename() for
move a directories.
The dnf_move_recursive() uses copy+delete fallback if native moving
of directory failed (eg. moving between filesystems, overlayfs).

https://bugzilla.redhat.com/show_bug.cgi?id=1700341
---
 libdnf/dnf-repo.cpp  | 19 +++++++++----------
 libdnf/repo/Repo.cpp | 12 ++++++++----
 2 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/libdnf/dnf-repo.cpp b/libdnf/dnf-repo.cpp
index a358356a..568e4262 100644
--- a/libdnf/dnf-repo.cpp
+++ b/libdnf/dnf-repo.cpp
@@ -36,6 +36,7 @@
 #include "conf/OptionBool.hpp"
 
 #include "hy-repo-private.hpp"
+#include "hy-iutil-private.hpp"
 
 #include <strings.h>
 #include <fcntl.h>
@@ -1826,14 +1827,13 @@ dnf_repo_update(DnfRepo *repo,
 
     /* move the packages directory from the old cache to the new cache */
     if (g_file_test(priv->packages, G_FILE_TEST_EXISTS)) {
-        rc = g_rename(priv->packages, priv->packages_tmp);
-        if (rc != 0) {
-            ret = FALSE;
+        ret = dnf_move_recursive(priv->packages, priv->packages_tmp, &error_local);
+        if (!ret) {
             g_set_error(error,
                         DNF_ERROR,
                         DNF_ERROR_CANNOT_FETCH_SOURCE,
-                        "cannot move %s to %s",
-                        priv->packages, priv->packages_tmp);
+                        "cannot move %s to %s: %s",
+                        priv->packages, priv->packages_tmp, error_local->message);
             goto out;
         }
     }
@@ -1844,14 +1844,13 @@ dnf_repo_update(DnfRepo *repo,
         goto out;
 
     /* rename .tmp actual name */
-    rc = g_rename(priv->location_tmp, priv->location);
-    if (rc != 0) {
-        ret = FALSE;
+    ret = dnf_move_recursive(priv->location_tmp, priv->location, &error_local);
+    if (!ret) {
         g_set_error(error,
                     DNF_ERROR,
                     DNF_ERROR_CANNOT_FETCH_SOURCE,
-                    "cannot move %s to %s",
-                    priv->location_tmp, priv->location);
+                    "cannot move %s to %s: %s",
+                    priv->location_tmp, priv->location, error_local->message);
         goto out;
     }
     ret = lr_handle_setopt(priv->repo_handle, error,
diff --git a/libdnf/repo/Repo.cpp b/libdnf/repo/Repo.cpp
index 23638839..0dbeed8b 100644
--- a/libdnf/repo/Repo.cpp
+++ b/libdnf/repo/Repo.cpp
@@ -31,6 +31,7 @@
 #include "../hy-iutil.h"
 #include "../hy-repo-private.hpp"
 #include "../hy-util-private.hpp"
+#include "../hy-iutil-private.hpp"
 #include "../hy-types.h"
 #include "libdnf/conf/ConfigParser.hpp"
 #include "libdnf/utils/File.hpp"
@@ -1155,10 +1156,13 @@ void Repo::Impl::fetch(const std::string & destdir, std::unique_ptr<LrHandle> &&
                 }
             }
             auto tempElement = tmpdir + "/" + elName;
-            if (rename(tempElement.c_str(), targetElement.c_str()) == -1) {
-                const char * errTxt = strerror(errno);
-                throw std::runtime_error(tfm::format(
-                    _("Cannot rename directory \"%s\" to \"%s\": %s"), tempElement, targetElement, errTxt));
+            GError * error = NULL;
+            if (!dnf_move_recursive(tempElement.c_str(), targetElement.c_str(), &error)) {
+                std::string errTxt = tfm::format(
+                    _("Cannot rename directory \"%s\" to \"%s\": %s"),
+                    tempElement, targetElement, error->message);
+                g_error_free(error);
+                throw std::runtime_error(errTxt);
             }
         }
     }
-- 
2.21.0