commit 828db8f98e5d3a589535a77b701454e2b7c2627b
Author: Federico Mena Quintero <federico@novell.com>
Date:   Tue Mar 10 15:28:05 2009 -0600

    bgo350976 - Translate EINVAL from libsmbclient to G_IO_ERROR_INVALID_FILENAME when appropriate
    
    Signed-off-by: Federico Mena Quintero <federico@novell.com>

diff --git a/ChangeLog b/ChangeLog
index 7117c51..3b5f599 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2009-03-10  Federico Mena Quintero  <federico@novell.com>
+
+	http://bugzilla.gnome.org/show_bug.cgi?id=350976 - libsmbclient
+	reports "invalid filename" as EINVAL.  Translate that to
+	G_IO_ERROR_INVALID_FILENAME when appropriate, so that the user
+	doesn't get an unfriendly message for G_IO_ERROR_INVALID_ARGUMENT.
+
+	* daemon/gvfsbackendsmb.c (set_error_from_filename_related_errno):
+	New function; translates EINVAL to "invalid filename" when appropriate.
+	(set_job_failed_from_filename_related_errno): New helper function;
+	analogous to g_vfs_job_failed_from_errno().
+	(do_open_for_read): Use the functions above.
+	(do_query_info_on_read): Likewise.
+	(do_create): Likewise.
+	(do_append_to): Likewise.
+	(do_replace): Likewise.
+	(do_query_info_on_write): Likewise.
+	(do_close_write): Likewise.
+	(do_query_info): Likewise.
+	(do_set_attribute): Likewise.
+	(do_enumerate): Likewise.
+	(do_set_display_name): Likewise.
+	(do_delete): Likewise.
+	(do_make_directory): Likewise.
+	(do_move): Likewise.
+
 2009-03-10  Alexander Larsson  <alexl@redhat.com>
 
 	Bug 563418 – gvfs backend leaks monitors
diff --git a/daemon/gvfsbackendsmb.c b/daemon/gvfsbackendsmb.c
index 74b8f3b..5fc1b32 100644
--- a/daemon/gvfsbackendsmb.c
+++ b/daemon/gvfsbackendsmb.c
@@ -101,6 +101,47 @@ static void set_info_from_stat (GVfsBackendSmb *backend,
 				const char *basename,
 				GFileAttributeMatcher *matcher);
 
+/* Instead of simply calling g_vfs_job_failed_from_error() or g_strerror(), you
+ * should call either of the following two functions when you get an error from
+ * a filename-related method (open, rename).  Other methods (read, write) should
+ * keep using the usual functions to set errors.
+ */
+
+static void
+set_error_from_filename_related_errno (GError **error, gint smb_errno)
+{
+  /* See http://bugzilla.gnome.org/show_bug.cgi?id=350976 - libsmbclient returns
+   * "invalid filename" as EINVAL, so we need to translate that; otherwise we'll
+   * get G_IO_ERROR_INVALID_ARGUMENT, which is not very explanatory to users.
+   */
+  gint code;
+  const char *msg;
+
+  if (smb_errno == EINVAL)
+    {
+      code = G_IO_ERROR_INVALID_FILENAME;
+      msg = _("invalid filename; please make sure it has only valid characters");
+    }
+  else
+    {
+      code = g_io_error_from_errno (errno_arg);
+      msg = g_strerror (errno_arg);
+    }
+
+  g_set_error_literal (error, G_IO_ERROR, code, msg);
+}
+
+static void
+set_job_failed_from_filename_related_errno (GVfsJob *job, gint smb_errno)
+{
+  GError *error;
+
+  error = NULL;
+  set_error_from_filename_related_errno (&error, smb_errno);
+  g_vfs_job_failed_from_error (job, error);
+  g_error_free (error);
+}
+
 
 static void
 g_vfs_backend_smb_finalize (GObject *object)
@@ -690,7 +731,7 @@ do_open_for_read (GVfsBackend *backend,
                               G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY,
                              _("Can't open directory"));
       else
-        g_vfs_job_failed_from_errno (G_VFS_JOB (job), olderr);
+        set_job_failed_from_filename_related_errno (G_VFS_JOB (job), olderr);
   }
   else
     {
@@ -798,7 +839,7 @@ do_query_info_on_read (GVfsBackend *backend,
       g_vfs_job_succeeded (G_VFS_JOB (job));
     }
   else
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), saved_errno);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), saved_errno);
 
 }
 
@@ -854,7 +895,7 @@ do_create (GVfsBackend *backend,
   g_free (uri);
 
   if (file == NULL)
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errno);
   else
     {
       handle = g_new0 (SmbWriteHandle, 1);
@@ -887,7 +928,7 @@ do_append_to (GVfsBackend *backend,
   g_free (uri);
 
   if (file == NULL)
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errno);
   else
     {
       handle = g_new0 (SmbWriteHandle, 1);
@@ -1085,9 +1126,7 @@ do_replace (GVfsBackend *backend,
     {
       int errsv = errno;
 
-      g_set_error_literal (&error, G_IO_ERROR,
-			   g_io_error_from_errno (errsv),
-			   g_strerror (errsv));
+      set_error_from_filename_related_errno (&error, errsv);
       goto error;
     }
   else if (file == NULL && errno == EEXIST)
@@ -1154,9 +1193,7 @@ do_replace (GVfsBackend *backend,
 	    {
               int errsv = errno;
 
-	      g_set_error_literal (&error, G_IO_ERROR,
-				   g_io_error_from_errno (errsv),
-				   g_strerror (errsv));
+	      set_error_from_filename_related_errno (&error, errsv);
 	      goto error;
 	    }
 	}
@@ -1282,7 +1319,7 @@ do_query_info_on_write (GVfsBackend *backend,
       g_vfs_job_succeeded (G_VFS_JOB (job));
     }
   else
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), saved_errno);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), saved_errno);
 
 }
 
@@ -1328,11 +1365,15 @@ do_close_write (GVfsBackend *backend,
 	  if (res ==  -1)
 	    {
               int errsv = errno;
+	      GError *tmp_err = NULL;
+
+	      smbc_unlink (op_backend->smb_context, handle->tmp_uri);
 
-          smbc_unlink (op_backend->smb_context, handle->tmp_uri);
+	      set_error_from_filename_related_errno (&tmp_err, errsv);
 	      g_vfs_job_failed (G_VFS_JOB (job),
 				G_IO_ERROR, G_IO_ERROR_CANT_CREATE_BACKUP,
-				_("Backup file creation failed: %s"), g_strerror (errsv));
+				_("Backup file creation failed: %s"), tmp_err->message);
+	      g_error_free (tmp_err);
 	      goto out;
 	    }
 	}
@@ -1344,7 +1385,7 @@ do_close_write (GVfsBackend *backend,
       if (res ==  -1)
 	{
 	  smbc_unlink (op_backend->smb_context, handle->tmp_uri);
-	  g_vfs_job_failed_from_errno (G_VFS_JOB (job), errno);
+	  set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errno);
 	  goto out;
 	}
     }
@@ -1553,7 +1594,7 @@ do_query_info (GVfsBackend *backend,
       g_vfs_job_succeeded (G_VFS_JOB (job));
     }
   else
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), saved_errno);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), saved_errno);
 
 }
 
@@ -1665,7 +1706,7 @@ do_set_attribute (GVfsBackend *backend,
   g_free (uri);
 
   if (res != 0)
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errsv);
   else
     g_vfs_job_succeeded (G_VFS_JOB (job));
 }
@@ -1707,9 +1748,7 @@ do_enumerate (GVfsBackend *backend,
       int errsv = errno;
 
       error = NULL;
-      g_set_error_literal (&error, G_IO_ERROR,
-			   g_io_error_from_errno (errsv),
-			   g_strerror (errsv));
+      set_error_from_filename_related_errno (&error, errsv);
       goto error;
     }
 
@@ -1825,7 +1864,7 @@ do_set_display_name (GVfsBackend *backend,
   g_free (to_uri);
 
   if (res != 0)
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errsv);
   else
     {
       g_vfs_job_set_display_name_set_new_path (job, new_path);
@@ -1858,12 +1897,15 @@ do_delete (GVfsBackend *backend,
   if (res == -1)
     {
       errsv = errno;
+      GError *tmp_err = NULL;
 
+      set_error_from_filename_related_errno (&tmp_err, errsv);
       g_vfs_job_failed (G_VFS_JOB (job),
 			G_IO_ERROR,
 			g_io_error_from_errno (errsv),
 			_("Error deleting file: %s"),
-			g_strerror (errsv));
+			tmp_err->message);
+      g_error_free (tmp_err);
       g_free (uri);
       return;
     }
@@ -1876,7 +1918,7 @@ do_delete (GVfsBackend *backend,
   g_free (uri);
 
   if (res != 0)
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errsv);
   else
     g_vfs_job_succeeded (G_VFS_JOB (job));
 }
@@ -1898,7 +1940,7 @@ do_make_directory (GVfsBackend *backend,
   g_free (uri);
 
   if (res != 0)
-    g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+    set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errsv);
   else
     g_vfs_job_succeeded (G_VFS_JOB (job));
 }
@@ -1932,12 +1974,15 @@ do_move (GVfsBackend *backend,
   if (res == -1)
     {
       errsv = errno;
+      GError *tmp_err = NULL;
 
+      set_error_from_filename_related_errno (&tmp_err, errsv);
       g_vfs_job_failed (G_VFS_JOB (job),
 			G_IO_ERROR,
 			g_io_error_from_errno (errsv),
 			_("Error moving file: %s"),
-			g_strerror (errsv));
+			tmp_err->message);
+      g_error_free (tmp_err);
       g_free (source_uri);
       return;
     }
@@ -2006,10 +2051,14 @@ do_move (GVfsBackend *backend,
       errsv = errno;
       if (res == -1)
 	{
+	  GError *tmp_err = NULL;
+
+	  set_error_from_filename_related_errno (&tmp_err, errsv);
 	  g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR,
 			    g_io_error_from_errno (errsv),
 			    _("Error removing target file: %s"),
-			    g_strerror (errsv));
+			    tmp_err->message);
+	  g_error_free (tmp_err);
 	  g_free (source_uri);
 	  g_free (dest_uri);
 	  return;
@@ -2034,7 +2083,7 @@ do_move (GVfsBackend *backend,
 			  G_IO_ERROR, G_IO_ERROR_WOULD_RECURSE,
 			  _("Can't recursively move directory"));
       else
-	g_vfs_job_failed_from_errno (G_VFS_JOB (job), errsv);
+	set_job_failed_from_filename_related_errno (G_VFS_JOB (job), errsv);
     }
   else
     g_vfs_job_succeeded (G_VFS_JOB (job));
