[gvfs] smb: Always check for existing file on rename



commit 62d2a521df6a7adf8a1dc9598e81947a56c9f3b9
Author: Tomas Bzatek <tbzatek redhat com>
Date:   Tue Aug 30 17:43:09 2011 +0200

    smb: Always check for existing file on rename
    
    Libsmbclient reports no error when target file or directory
    exists and overwrites target file.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=616645

 daemon/gvfsbackendsmb.c |   24 +++++++++++++++++++++---
 1 files changed, 21 insertions(+), 3 deletions(-)
---
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index 92507eb..1dbe8d8 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -1892,7 +1892,9 @@ do_set_display_name (GVfsBackend *backend,
   char *from_uri, *to_uri;
   char *dirname, *new_path;
   int res, errsv;
+  struct stat st;
   smbc_rename_fn smbc_rename;
+  smbc_stat_fn smbc_stat;
 
   dirname = g_path_get_dirname (filename);
 
@@ -1906,12 +1908,24 @@ do_set_display_name (GVfsBackend *backend,
   from_uri = create_smb_uri (op_backend->server, op_backend->share, filename);
   to_uri = create_smb_uri (op_backend->server, op_backend->share, new_path);
   
+
+  /* We can't rely on libsmbclient reporting EEXIST, let's always stat first.
+   * https://bugzilla.gnome.org/show_bug.cgi?id=616645
+   */
+  smbc_stat = smbc_getFunctionStat (op_backend->smb_context);
+  res = smbc_stat (op_backend->smb_context, to_uri, &st);
+  if (res == 0)
+    {
+      g_vfs_job_failed (G_VFS_JOB (job),
+                        G_IO_ERROR, G_IO_ERROR_EXISTS,
+                        _("Can't rename file, filename already exists"));
+      goto out;
+    }
+
   smbc_rename = smbc_getFunctionRename (op_backend->smb_context);
   res = smbc_rename (op_backend->smb_context, from_uri,
-					 op_backend->smb_context, to_uri);
+                     op_backend->smb_context, to_uri);
   errsv = errno;
-  g_free (from_uri);
-  g_free (to_uri);
 
   if (res != 0)
     g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
@@ -1920,6 +1934,10 @@ do_set_display_name (GVfsBackend *backend,
       g_vfs_job_set_display_name_set_new_path (job, new_path);
       g_vfs_job_succeeded (G_VFS_JOB (job));
     }
+
+ out:
+  g_free (from_uri);
+  g_free (to_uri);
   g_free (new_path);
 }
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]