[easytag] Handle renaming on case-insensitive filesystems
- From: David King <davidk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [easytag] Handle renaming on case-insensitive filesystems
- Date: Thu, 25 Sep 2014 17:07:50 +0000 (UTC)
commit 656946c80805acc39c3102c1dff480658064bb8c
Author: David King <amigadave amigadave com>
Date: Thu Sep 25 17:57:39 2014 +0100
Handle renaming on case-insensitive filesystems
A rename will fail on a filesystem that is case-insensitive, if the
filenames only differ by case. Work around this by moving to a temporary
file first, in the case that a rename fails because the target exists.
https://bugzilla.gnome.org/show_bug.cgi?id=737302
src/easytag.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 72 insertions(+), 5 deletions(-)
---
diff --git a/src/easytag.c b/src/easytag.c
index f026e13..f4fd4be 100644
--- a/src/easytag.c
+++ b/src/easytag.c
@@ -790,17 +790,84 @@ et_rename_file (const char *old_filepath, const char *new_filepath,
if (!g_file_move (file_old, file_new, G_FILE_COPY_NONE, NULL, NULL, NULL,
error))
{
- /* Error moving file. */
- g_object_unref (file_old);
- g_object_unref (file_new);
- g_assert (error == NULL || *error != NULL);
- return FALSE;
+ if (g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ /* Possibly a case change on a case-insensitive filesystem. */
+ /* TODO: casefold the paths of both files, and check to see whether
+ * they only differ by case? */
+ gchar *tmp_filename;
+ mode_t old_mode;
+ gint fd;
+ GFile *tmp_file;
+ GError *tmp_error = NULL;
+
+ tmp_filename = g_strconcat (old_filepath, ".XXXXXX", NULL);
+
+ old_mode = umask (077);
+ fd = mkstemp (tmp_filename);
+ umask (old_mode);
+
+ if (fd >= 0)
+ {
+ close (fd);
+ }
+
+ tmp_file = g_file_new_for_path (tmp_filename);
+ g_free (tmp_filename);
+
+ if (!g_file_move (file_old, tmp_file, G_FILE_COPY_OVERWRITE, NULL,
+ NULL, NULL, &tmp_error))
+ {
+ g_file_delete (tmp_file, NULL, NULL);
+
+ g_object_unref (tmp_file);
+ g_clear_error (error);
+ g_propagate_error (error, tmp_error);
+ goto err;
+ }
+ else
+ {
+ /* Move to temporary file succeeded, now move to the real new
+ * location. */
+ if (!g_file_move (tmp_file, file_new, G_FILE_COPY_NONE, NULL,
+ NULL, NULL, &tmp_error))
+ {
+ g_file_move (tmp_file, file_old, G_FILE_COPY_NONE, NULL,
+ NULL, NULL, NULL);
+ g_object_unref (tmp_file);
+ g_clear_error (error);
+ g_propagate_error (error, tmp_error);
+ goto err;
+ }
+ else
+ {
+ /* Move succeeded, so clear the original error about the
+ * new file already existing. */
+ g_object_unref (tmp_file);
+ g_clear_error (error);
+ goto out;
+ }
+ }
+ }
+ else
+ {
+ /* Error moving file. */
+ goto err;
+ }
}
+out:
g_object_unref (file_old);
g_object_unref (file_new);
g_assert (error == NULL || *error == NULL);
return TRUE;
+
+err:
+ g_object_unref (file_new_parent);
+ g_object_unref (file_old);
+ g_object_unref (file_new);
+ g_assert (error == NULL || *error != NULL);
+ return FALSE;
}
/*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]